home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume25 / QBATCH / part05 < prev    next >
Text File  |  1991-11-04  |  46KB  |  1,456 lines

  1. Newsgroups: comp.sources.misc
  2. From: alan@tharr.UUCP (Alan Saunders)
  3. Subject:  v25i024:  QBATCH - a queued batch processing system for UNIX, Part05/06
  4. Message-ID: <1991Nov5.034852.5158@sparky.imd.sterling.com>
  5. X-Md4-Signature: c94ab58832177a5cae6e94b86d55bf1f
  6. Date: Tue, 5 Nov 1991 03:48:52 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: alan@tharr.UUCP (Alan Saunders)
  10. Posting-number: Volume 25, Issue 24
  11. Archive-name: QBATCH/part05
  12. Environment: UNIX
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then unpack
  16. # it by saving it into a file and typing "sh file".  To overwrite existing
  17. # files, type "sh file -c".  You can also feed this as standard input via
  18. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  19. # will see the following message at the end:
  20. #        "End of archive 5 (of 6)."
  21. # Contents:  doc/chap.04 src/jk.c src/js.c src/qf.c
  22. # Wrapped by root@vfib_d on Thu Oct 31 15:46:40 1991
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. if test -f 'doc/chap.04' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'doc/chap.04'\"
  26. else
  27. echo shar: Extracting \"'doc/chap.04'\" \(10173 characters\)
  28. sed "s/^X//" >'doc/chap.04' <<'END_OF_FILE'
  29. X             QBATCH .. a queued batch processing system for UNIX
  30. X
  31. X
  32. X         The QBATCH system and its related programs were
  33. X         written by Alan D. Saunders and are
  34. X         Copyright (c) Vita Services Ltd. 1990 and
  35. X         Copyright (c) Vita Fibres Ltd. 1991
  36. X
  37. X4. USER commands.
  38. X    
  39. X    Note: this is a descriptive text. Full details of all the QBATCH commands
  40. X    are provided in the relevant man pages.  There is also a man page for QBATCH
  41. X    which contains a summary of all QBATCH commands.
  42. X    See also ADMINISTRATIVE commands.
  43. X
  44. X    qa    Queue availability.  For a given user running qa, the accessibility of
  45. X    all queues is checked.  All fixed context queues are checked to see if
  46. X    this user is permitted (by uid or gid) to submit jobs.  All fixed
  47. X    context queues which permit this user to submit, and all open queues
  48. X    are listed with a brief (one line) description.
  49. X    viz:
  50. X
  51. X    Queues available to alan
  52. X
  53. X    Queue       No.         Priority       Fixed   Enabled Halted  Stopped
  54. X    Name     Entries      (nice)      Context
  55. X
  56. X    fasq          2        -5         no          yes     no      no
  57. X    fault          0         0         no          yes     no      no
  58. X    fcon         14        10         yes      yes     no      yes
  59. X    fcsq          4         5         no          yes     no      no
  60. X    fcst          1        -5         no          yes     no      no
  61. X    intq          0         0         no          no      no      no
  62. X    invq          1         0         no          yes     no      no
  63. X    mant          2        -5         no          yes     no      no
  64. X    masq          2        -5         no          yes     no      no
  65. X    mbsq          0        10         no          no      no      no
  66. X    slwq          8        15         no          yes     no      no
  67. X    sopq          4         5         no          yes     no      no
  68. X    sopt          3        -5         no          yes     no      no
  69. X    work         14        10         no          yes     no      no
  70. X
  71. X    js    Job submit.  This is used to submit jobs to a QBATCH queue.
  72. X    By default, a job is run under the bourne shell.  This may be
  73. X    overridden by using the -s option to js, or in the case of a fixed
  74. X    context queue, by the first line of the control file.  Jobs submitted
  75. X    to a queue must be valid in terms of the syntax of the shell under
  76. X    which the job is to be run.  This said, jobs may consist of anything
  77. X    that can be run interactively provided they don't attempt to access
  78. X    what may be unavailable resources, in particular, the vdu of the
  79. X    submittor.  If the programs, or scripts use stdout and stderr for
  80. X    output, and (redirected) stdin for input, then they can be submitted to
  81. X    a queue.  Programs which attempt to open /dev/tty may fail altogether
  82. X    since QBATCH jobs do not have a controlling terminal.  On some systems
  83. X    they may use /dev/console instead. (this seems to be the case in SunOS
  84. X    on SPARCstations.)
  85. X
  86. X    js will accept the job either as a named file, or from stdin.  This
  87. X    allows regularly run jobs to be set up as 'jcl' files, and submitted
  88. X    as:
  89. X    js <queuename> <jclfile>
  90. X    Alternatively, stdin can be used, either directly:
  91. X    js <queuename>
  92. X    <commands>
  93. X    [..]
  94. X    ^D
  95. X    Or as a here document:
  96. X    js <queuename> <<EOjob
  97. X    <commands>
  98. X    [..]
  99. X    EOjob
  100. X
  101. X    If submitted as a file, the 'jcl' may be created in a script, using
  102. X    prompts, and shell parameters etc to set it up.
  103. X
  104. X    js can also be used as the destination of a pipeline in the shell, or
  105. X    as a pipe (opened for write access) in a c program.
  106. X
  107. X    Main options:
  108. X
  109. X    -n <name>    This provides a meaningful name for the job.  It's only
  110. X            use is to give some meaning to the ql output (see
  111. X            later).
  112. X
  113. X    -m <monitor>    The monitor (combined stdout and stderr) for a job is
  114. X            normally determined automatically, either by js or qp.
  115. X            (monitors are discussed later.)  This option allows a
  116. X            user to define exactly where the monitor for this job
  117. X            will be written it should be a fully specified absolute
  118. X            pathspec..
  119. X
  120. X    -s <shell>    As mentioned earlier, jobs are by default run under the
  121. X            bourne shell.  If the queue is fixed context, the shell
  122. X            may be specified in the control file.  This option
  123. X            allows the user to specify the shell under which this
  124. X            job will be run.
  125. X
  126. X    -r <reply code> When the process engine has finished with a job, it
  127. X            normally silently looks for the next.  The reply code,
  128. X            if non-zero causes qp to execute a script called
  129. X            jobdone, which will notify the submittor as follows:
  130. X            reply code 0 No reply.
  131. X                   1 Write a message on the submittor's tty.
  132. X                   2 Mail a message to the user.
  133. X            Any other value (or not set).. no reply.
  134. X
  135. X    jk    Job kill.  This allows the user to remove a job from a queue if they
  136. X    own it.  The super user may kill any or all jobs in any and all queues.
  137. X    an ordinary user may kill only jobs that they themselves submitted.
  138. X    If the job is actually running, jk will refuse to remove the job unless
  139. X    the -k option is specified.
  140. X
  141. X    jm  Job monitor.  This allows the addition of a monitor spec (see js) as an
  142. X    afterthought.
  143. X
  144. X    jn  Job name.  Allows the addition of a job name as an afterthought.
  145. X
  146. X    jr  Job repeat.  This allows the current job being processed to be
  147. X    repeated.  If the -k option is used, the repeat flag will be set, and
  148. X    the job will be repeated.  This allows for example, a print job
  149. X    printing on the wrong stationary to be restarted.
  150. X
  151. X    jj  Job jump.  NB. This does not allow ANYBODY to jump the queue!
  152. X    This allows any user to re- order a consecutive group of their own jobs
  153. X    in a queue, by jumping a job above an adjacent prior job owned by the
  154. X    same user.  Only the administrator is permitted to jump jobs above
  155. X    those with different owner id's.
  156. X    No job may be jumped above a currently running job.
  157. X
  158. X    ql    Queue list. List the contents and status of a QBATCH queue.
  159. X    The queue header data and flags are displayed, along with a line for
  160. X    each job currently in the queue.  The data are more meaningful if job
  161. X    names are used when the jobs are submitted.
  162. X    viz:
  163. X
  164. X    Status of           : work 
  165. X    Spooling in         : /var/spool/batch/
  166. X    Monitor is          : /var/spool/batch/work.mon
  167. X    Priority is         : 10
  168. X    Queue last started  : 12/09/91 09:02:37
  169. X    Current job started :  2/10/91 14:54:30
  170. X
  171. X       No of    Active   Queue      Job       Job      Queue     Queue
  172. X      Entries   (pid)  Accepting Repeated    Killed    Halted   Stopped
  173. X          13    428       Yes       No        No        No        No
  174. X
  175. X      2    569 root        ttyp0      2/10/91 14:55:10  UUCP Log Analysis
  176. X      3        andy        tty01      2/10/91 14:59:29  Sales Report
  177. X      4        root        console    2/10/91 15:01:00  Security Check
  178. X      5        accounts    ttyh3      2/10/91 15:03:20  Statements Print
  179. X      6        jmajor      tty0a      2/10/91 15:05:31  COBOL compile
  180. X      7        bfrances    ttyp3      2/10/91 15:05:31  exit 0
  181. X      8        james       ttyc       2/10/91 15:07:32  find ./ -name core -ls
  182. X      9        james       ttyc       2/10/91 15:08:12  test run 1
  183. X     10        andy        tty01      2/10/91 15:08:34  Invoice Print
  184. X     11        root        ttyp0      2/10/91 15:10:04  Offline Backup
  185. X     12        accounts    ttyh3      2/10/91 15:10:17  Overdue list
  186. X     13        prog1       ttypb      2/10/91 15:11:35  make emacs
  187. X     14        jmajor      tty0a      2/10/91 15:11:36  cobrun update.cbl
  188. X
  189. X          The output of 'ql' is in three parts:
  190. X
  191. X          a. At the top is the basic information about the queue itself. The
  192. X         name, which files it uses, it's priority, etc.
  193. X
  194. X          b. The next part shows the current status of the queue header flags
  195. X         and fields, which are self explanatory.  The field headed 'Active'
  196. X         in this case contains the pid of the queue process engine ('qp')
  197. X         which is handling this queue.  If the queue was idle (no process
  198. X         engine) this field would contain "No".
  199. X
  200. X          c. The bulk of the output consists of a list of the entries in the
  201. X         queue, each starting with the entry number.  It is this number
  202. X         which is used to manipulate individual entries in the queue
  203. X         (e.g. jk -e <entryno> <queuename> to kill (remove) a job).
  204. X
  205. X         The next column is only ever used for the first entry in a queue,
  206. X         and only then if the queue is active.  The first entry in the queue
  207. X         is the currently running entry, and this field contains the pid of
  208. X         the forked child.
  209. X
  210. X         Column 3 is the user who submitted the job.
  211. X
  212. X         Column 4 is the tty from which the job was submitted.
  213. X
  214. X         Columns 5 & 6 are the date & time that the job was submitted.
  215. X
  216. X         Column 7 is the job name, which, if used, gives some indication
  217. X         of the job running.
  218. X         
  219. X    qf     Queue find.
  220. X    qt    Queue test. These programs are primarily provided for use in shell
  221. X    scripts.  All of the options of qf provide output on stdout relating to
  222. X    the contents and status of a queue.  Most of the options to qt cause it
  223. X    to either fail, or not fail depending on the settings of the queue
  224. X    flags.  The exception is the -l option which is used in the qa script
  225. X    to check the accessibility of a queue, and output the one line
  226. X    description.
  227. X    Examine the scripts rc.QBATCH and qa for examples of their use.
  228. X
  229. X    Those options to qf which are useful interactively are:
  230. X    -m  Monitor. qf returns the full absolute pathspec of the monitor
  231. X        used by the queue (see also MONITORS).  So to check the progress
  232. X        of a job, the user can use:
  233. X        more `qf -m <queuename>`
  234. X
  235. X    -l  Provides a one line status report similar to qt -l but with the
  236. X        columns headed.
  237. X
  238. X    -j  jcl. returns the full absolute pathspec of the jcl file created by
  239. X        js for this job.
  240. X
  241. X    -s  Summary timings.  qp maintains a limited profile timing summary for
  242. X        jobs processed in each queue.  The timings for each job are written
  243. X        to the monitor, but qf -s will display the summary viz:
  244. X
  245. X
  246. X         Queue started     : Wed Oct  2 15:02:37 1991
  247. X
  248. X         Available for     : 5 Min 14.00 Sec
  249. X         No. Jobs Processed: 10
  250. X
  251. X        Times:            Actual            Av. Per Job
  252. X
  253. X        Queued             5:45.00 Sec               34.50 Sec
  254. X        Real             1:43.68 Sec               10.36 Sec
  255. X        User                0.60 Sec                0.06 Sec
  256. X        System                2.69 Sec                0.26 Sec
  257. X
  258. X        Utilisation (real/available) 33.01%
  259. X
  260. X        Current job not accounted for above, running for : 7.00 Sec
  261. X
  262. X       The figures are:
  263. X       Queued:    The time a job was on the queue before starting to process.
  264. X       Real:    The actual (wall clock) time from start to end of processing.
  265. X       User:    The user cpu time taken by the job.
  266. X       System:    The system cpu time taken by the job.
  267. X
  268. END_OF_FILE
  269. if test 10173 -ne `wc -c <'doc/chap.04'`; then
  270.     echo shar: \"'doc/chap.04'\" unpacked with wrong size!
  271. fi
  272. # end of 'doc/chap.04'
  273. fi
  274. if test -f 'src/jk.c' -a "${1}" != "-c" ; then 
  275.   echo shar: Will not clobber existing file \"'src/jk.c'\"
  276. else
  277. echo shar: Extracting \"'src/jk.c'\" \(8327 characters\)
  278. sed "s/^X//" >'src/jk.c' <<'END_OF_FILE'
  279. X/************************************************************************/  
  280. X/*                                                                      */
  281. X/* jk .. Job kill. remove a job from this queue (optionally kill it).   */
  282. X/*                                                                      */
  283. X/*      usage: jk [-k] [-a] [-u <userid>] [-e <entryno>]  qname         */
  284. X/*                                                                      */
  285. X/*   Copyright (c) Vita Services 1990                                   */
  286. X/*             (c) Vita Fibres   1990 1991                              */
  287. X/*                                                                      */
  288. X/************************************************************************/
  289. X
  290. X#include "qbatch.h"
  291. int fpq = 0;
  292. int i, l;
  293. int killed = 0;
  294. long  j, k;
  295. int aflag = 0, kflag = 0, entryno = 0;
  296. pid_t jpid = 0;
  297. uid_t userid = 0, uid;
  298. off_t *entries;
  299. char *queuename;
  300. char queue[128];
  301. char buff [128];                            
  302. X#include "config.h"
  303. X                            
  304. X
  305. main (argc, argv, envp)
  306. int argc;
  307. char *argv[], *envp[];
  308. X{
  309. X    int c;
  310. X    extern char *optarg;
  311. X    extern int optind;
  312. X    if (argc == 1)
  313. X    {
  314. X        puts ("Usage: jk [-a] [-u <userid>] [-e <entryno>]  qname");
  315. X        qb_term (0);
  316. X    }
  317. X    while ((c = getopt (argc, argv, "kau:e:v")) != -1)
  318. X    switch (c)
  319. X    {
  320. X        case 'a':   aflag ++;
  321. X                    break;
  322. X        case 'u':   userid = atoi(optarg);
  323. X                    break;
  324. X        case 'v':   q_version();
  325. X        case 'k':   kflag ++;
  326. X                    break;
  327. X        case 'e':   entryno = atoi(optarg);
  328. X                    break;                    
  329. X    case '?':   qb_term (-1);
  330. X    }
  331. X    if (optind >= argc)
  332. X    {
  333. X        fprintf (stderr, "Missing queue name\n");
  334. X        qb_term (-1);
  335. X    }
  336. X    if ((aflag !=0) && (entryno != 0))
  337. X    {
  338. X        fprintf (stderr, "-a (ALL) flag and -e (entry number) incompatible\n");
  339. X        qb_exit (-1);
  340. X    }
  341. X    uid = getuid();
  342. X    if ((aflag ==0) && (entryno == 0))
  343. X    {
  344. X        if (uid == 0) kflag = 999;
  345. X        else
  346. X        {
  347. X            fprintf (stderr, "Must have one of -a (ALL) flag or -e (entry number)\n");
  348. X            qb_exit (-1);
  349. X        }
  350. X    }
  351. X        
  352. X    queuename = argv[optind];
  353. X    strcpy (queue, QUEUEPATH);
  354. X    strcat (queue, queuename);
  355. X    qb_setterm();
  356. X    fpq = open (queue, O_RDWR);
  357. X    if (fpq == -1)
  358. X    {
  359. X        fprintf (stderr, "Invalid queue name: %s\n", queuename);
  360. X        qb_term (-1); 
  361. X    }
  362. X    
  363. X    q_lock(fpq);
  364. X    read  (fpq, &head, sizeof(head));
  365. X    if (bad_queue()) qb_exit(-1);
  366. X    if (head.qh_noentries == 0)
  367. X    {
  368. X        fprintf (stderr, " Queue %s is empty!\n", queuename);
  369. X        qb_term (-1);
  370. X    }
  371. X    if (uid != 0)
  372. X    {
  373. X        if ((userid != uid)&&(userid != 0) && (aflag == 0))
  374. X        {
  375. X            fprintf (stderr, "Must be  super user to kill another's jobs)\n");
  376. X            qb_term (-1);
  377. X        }
  378. X    }
  379. X    if (kflag == 999)
  380. X    {
  381. X        if ((head.qh_flags & qh_kill) == 0) head.qh_flags += qh_kill;
  382. X        lseek (fpq, 0, SEEK_SET);
  383. X        write (fpq, &head, sizeof(head));
  384. X        q_unlock(fpq);
  385. X        close (fpq);fpq = 0;
  386. X        tell_qp();
  387. X        qb_exit (0);        
  388. X    }
  389. X    if ((head.qh_flags&qh_halt)  == 0)
  390. X    {
  391. X        head.qh_flags += qh_halt;
  392. X        lseek (fpq, 0, SEEK_SET);
  393. X        write (fpq, &head, sizeof(head));
  394. X        q_unlock(fpq);
  395. X        close (fpq);fpq = 0;
  396. X        tell_qp();
  397. X    }
  398. X    do
  399. X    {
  400. X        fpq = open (queue, O_RDWR);
  401. X    q_lock(fpq);
  402. X        read  (fpq, &head, sizeof(head));
  403. X        read  (fpq, &entry, sizeof(entry));
  404. X        jpid = entry.qe_status;
  405. X        if (jpid != 0)  /* something running */
  406. X        {
  407. X            q_unlock(fpq);
  408. X        close (fpq);fpq = 0;
  409. X            fpq = open (queue, O_RDWR);
  410. X        q_lock(fpq);
  411. X            read  (fpq, &head, sizeof(head));
  412. X        if (head.qh_noentries == 0)
  413. X            {
  414. X                    fprintf (stderr, " Queue %s is empty!\n", queuename);
  415. X                    qb_term (-1);
  416. X                }
  417. X            read  (fpq, &entry, sizeof(entry));
  418. X            if ((entry.qe_status != jpid) && (jpid != 0))   /* job has changed */
  419. X            {
  420. X                jpid = 0;                  /* don't kill */
  421. X            }
  422. X        }
  423. X    }
  424. X    while (jpid != entry.qe_status)    ;
  425. X    /* the current job is halted */
  426. X    if (jpid == 0) kflag = 0; /* nowt running, no need to kill */
  427. X    if ((uid != 0) && (uid != entry.qe_uid) && (aflag == 0))
  428. X    {
  429. X        fprintf (stderr, "Must be  super user to kill another's jobs)\n");
  430. X        lseek (fpq, 0, SEEK_SET);
  431. X        if ((head.qh_flags & qh_halt) != 0)
  432. X        {
  433. X             head.qh_flags -= qh_halt;
  434. X        }
  435. X        write (fpq, &head, sizeof(head));
  436. X        qb_exit (-1);
  437. X    }
  438. X        
  439. X    entries = (off_t *) calloc ((head.qh_noentries+1), sizeof(off_t));
  440. X    lseek (fpq, sizeof(head), SEEK_SET);
  441. X    l = 0;
  442. X    for (i = 0; i < head.qh_noentries; i++)
  443. X    {
  444. X        j = lseek (fpq, 0L, SEEK_CUR);
  445. X        read (fpq, &entry, sizeof(entry));
  446. X        if ((uid == 0) || (uid == entry.qe_uid)) /* we can kill it */
  447. X        {
  448. X            if (aflag)              /* kill all */
  449. X            {
  450. X                if ((uid == 0) && (userid == entry.qe_uid))
  451. X                    {       /* we don't want this */
  452. X                        killed++;
  453. X                        strcpy (buff, head.qh_spool);
  454. X                        if (buff[strlen(buff) -1] != '/') strcat (buff, "/");
  455. X                        strcat (buff, entry.qe_jcl);
  456. X                        if (entry.qe_status == 0) unlink (buff);
  457. X                        continue;
  458. X                    }
  459. X        if (userid == 0)
  460. X        {
  461. X            if (uid == entry.qe_uid)
  462. X                {       /* or this */
  463. X                killed ++;
  464. X                strcpy (buff, head.qh_spool);
  465. X                if (buff[strlen(buff) -1] != '/') strcat (buff, "/");
  466. X                strcat (buff, entry.qe_jcl);
  467. X                if (entry.qe_status == 0) unlink (buff);
  468. X                continue;
  469. X                }
  470. X            if (uid == 0)
  471. X                {       /* or this */
  472. X                killed ++;
  473. X                strcpy (buff, head.qh_spool);
  474. X                if (buff[strlen(buff) -1] != '/') strcat (buff, "/");
  475. X                strcat (buff, entry.qe_jcl);
  476. X                if (entry.qe_status == 0) unlink (buff);
  477. X                continue;
  478. X                }
  479. X        }
  480. X            }
  481. X            else 
  482. X            {                       /* just a given entry */
  483. X                if (entry.qe_jobno == entryno)
  484. X                    
  485. X                    {       /* or this */
  486. X                        killed ++;
  487. X                        strcpy (buff, head.qh_spool);
  488. X                        if (buff[strlen(buff) -1] != '/') strcat (buff, "/");
  489. X                        strcat (buff, entry.qe_jcl);
  490. X                        if (entry.qe_status == 0) 
  491. X                        {
  492. X                            unlink (buff);
  493. X                            kflag = 0;
  494. X                        }
  495. X                        continue;
  496. X                    }
  497. X            }
  498. X        }
  499. X        entries[l] = j; /* we must want it */
  500. X        l++;
  501. X    }
  502. X    /* we now have a table (entries) containing the offsets of those wanted */
  503. X    k = lseek (fpq, sizeof(head), SEEK_SET);
  504. X    head.qh_noentries = 0;
  505. X    if (k != entries[0])
  506. X    {   /* we don't want the first entry */
  507. X        if (jpid != 0)  /* job running so qp must cancel */
  508. X        {
  509. X            read (fpq, &entry, sizeof(entry)); /* skip first */
  510. X            if (kflag == 0)
  511. X            {
  512. X                printf ("Kill option not requested .. running entry not killed!\n");
  513. X                killed --;
  514. X            }
  515. X            head.qh_noentries ++;
  516. X        }
  517. X    }
  518. X    i = 0;
  519. X    while (entries[i] != 0)
  520. X    {
  521. X        k = lseek (fpq, 0L, SEEK_CUR);    /* write offset */
  522. X        lseek (fpq, entries[i], SEEK_SET); /* read offset */
  523. X        read  (fpq, &entry, sizeof(entry));
  524. X        lseek (fpq, k, SEEK_SET);
  525. X        write (fpq, &entry, sizeof(entry));
  526. X        head.qh_noentries ++;
  527. X    i++;
  528. X    }
  529. X    k = lseek (fpq, 0L, SEEK_CUR);
  530. X    lseek (fpq, 0, SEEK_SET);
  531. X    if ((head.qh_flags & qh_halt) != 0)
  532. X    {
  533. X        head.qh_flags -= qh_halt;
  534. X    }
  535. X    if (killed == 0) kflag = 0;
  536. X    if ((head.qh_flags & qh_kill) == 0)
  537. X    {
  538. X        if (kflag != 0) head.qh_flags += qh_kill;
  539. X    }
  540. X    write (fpq, &head, sizeof(head));
  541. X    ftruncate(fpq, k);
  542. X    /* right, now either kill or continue first entry (if running) */
  543. X    q_unlock(fpq);
  544. X    close (fpq);fpq = 0;
  545. X    tell_qp();
  546. X    printf ("Queue %s, %d entries killed\n", queuename, killed);
  547. X    exit (0);
  548. X}
  549. X
  550. END_OF_FILE
  551. if test 8327 -ne `wc -c <'src/jk.c'`; then
  552.     echo shar: \"'src/jk.c'\" unpacked with wrong size!
  553. fi
  554. # end of 'src/jk.c'
  555. fi
  556. if test -f 'src/js.c' -a "${1}" != "-c" ; then 
  557.   echo shar: Will not clobber existing file \"'src/js.c'\"
  558. else
  559. echo shar: Extracting \"'src/js.c'\" \(14536 characters\)
  560. sed "s/^X//" >'src/js.c' <<'END_OF_FILE'
  561. X/************************************************************************/  
  562. X/*                                                                      */
  563. X/* js .. job submit. submit a job to an existing queue.                 */
  564. X/*                                                                      */
  565. X/* Usage js [-l] [-d] [-r<replycode>] [-m<monitor>] [-n<jobname>]       */ 
  566. X/*          queuename [<jclfile>]                                       */
  567. X/*                                                                      */
  568. X/*   Copyright (c) Vita Services 1990                                   */
  569. X/*             (c) Vita Fibres   1990 1991                              */
  570. X/*                                                                      */
  571. X/************************************************************************/
  572. X
  573. X#include "qbatch.h"
  574. X#include <stdlib.h>
  575. X#include <malloc.h>
  576. int fpq = 0;
  577. XFILE *fpin, *fpout, *fp;
  578. char temp [16], *jcl, *jcwd = NULL;
  579. int i,j,k, debug = 0;
  580. int qpuid[10];
  581. int qpgid[10];
  582. int lflag = 0, sflag = 0, fixedcontext = 0, permission = -1;
  583. int gotuid, gotgid;
  584. uid_t jobuid, saveuid, testuid;
  585. gid_t jobgid, savegid; 
  586. int envcount = 0;
  587. int notify = 0;
  588. char envar[64];
  589. char *fcptr;
  590. char shell [64] = "";
  591. char monitor[64] = "";
  592. char jobname[32];
  593. char *tty;
  594. char *queuename;
  595. char jclfile[128];
  596. char queue[128];
  597. char buff [256];                            
  598. char rcmd [128];
  599. struct envlist {
  600. X    char *envptr;
  601. X    struct envlist *left;
  602. X    struct envlist *right;
  603. X       };
  604. struct envlist *root = (struct envlist *) NULL;
  605. X#include "config.h"
  606. int scan_envlist (ptr, str)
  607. struct envlist *ptr;
  608. char *str;
  609. X{
  610. X    int found;
  611. X    if (ptr == (struct envlist*) NULL) return (0);
  612. X    found = strcmp (str, ptr->envptr);
  613. X    if (found < 0) return (scan_envlist(ptr->left, str));
  614. X    if (found == 0) return (1);
  615. X    return (scan_envlist(ptr->right, str));
  616. X}
  617. int free_envlist (ptr)
  618. struct envlist *ptr;
  619. X{
  620. X    if (ptr == (struct envlist *) NULL) return;
  621. X    if (ptr->left != (struct envlist *) NULL)
  622. X    {
  623. X        (free_envlist(ptr->left));
  624. X        free (ptr->left);
  625. X    }
  626. X    if (ptr->right != (struct envlist *) NULL)
  627. X    {
  628. X        (free_envlist(ptr->right));
  629. X        free (ptr->right);
  630. X    }
  631. X}
  632. X                            
  633. int add_envlist (ptr, str)
  634. struct envlist *ptr;
  635. char *str;
  636. X{
  637. X    int found;
  638. X    if (ptr == (struct envlist *) NULL)
  639. X    {
  640. X        if (ptr != root) return (-1);
  641. X        ptr = (struct envlist *) malloc (sizeof(struct envlist));
  642. X        ptr->envptr = malloc(strlen(str)+1);
  643. X        strcpy (ptr->envptr, str);
  644. X        ptr->left = (struct envlist *) NULL;
  645. X        ptr->right = (struct envlist *) NULL;
  646. X        root = ptr;
  647. X        return (1);
  648. X
  649. X        }
  650. X    found = strcmp (str, ptr->envptr);
  651. X    if (found < 0)
  652. X    {
  653. X        if (ptr->left == (struct envlist *) NULL)
  654. X        {
  655. X            ptr->left = (struct envlist *) malloc (sizeof(struct envlist));
  656. X            ptr->left->envptr = malloc(strlen(str)+1);
  657. X            strcpy (ptr->left->envptr, str);
  658. X            ptr->left->left = (struct envlist *) NULL;
  659. X            ptr->left->right = (struct envlist *) NULL;
  660. X            return (1);
  661. X        }
  662. X        else 
  663. X        return (add_envlist (ptr->left, str));
  664. X    }
  665. X    if (found == 0) return (0); /* already in list */
  666. X    if (ptr->right == (struct envlist *) NULL)
  667. X    {
  668. X        ptr->right = (struct envlist *) malloc (sizeof(struct envlist));
  669. X        ptr->right->envptr = malloc(strlen(str)+1);
  670. X        strcpy (ptr->right->envptr, str);
  671. X        ptr->right->left = (struct envlist *) NULL;
  672. X        ptr->right->right = (struct envlist *) NULL;
  673. X        return (1);
  674. X    }
  675. X    else 
  676. X    return (add_envlist (ptr->right, str));
  677. X}
  678. X
  679. void usage(i)
  680. int i;
  681. X{
  682. X        puts ("Usage: js [-r<replycode>] [-m<monitor>] [-n<jobname>] [-s <shell>] queuename [<jclfile>]");
  683. X        qb_term (i);
  684. X}
  685. main (argc, argv, envp)
  686. int argc;
  687. char *argv[], *envp[];
  688. X{
  689. X    int c;
  690. X    extern char *optarg;
  691. X    extern int optind;
  692. X    if (argc == 1) usage (0);
  693. X    while ((c = getopt (argc, argv, "dlm:n:r:s:v")) != -1)
  694. X    switch (c)
  695. X    {
  696. X        case 'd':   if (shell[0] == 0) debug ++;
  697. X                    break;
  698. X        case 'l':   lflag ++;
  699. X                    break;
  700. X        case 'm':   if (strlen(optarg) >63)
  701. X                    {
  702. X                        fprintf (stderr, "Monitor path longer than 63 bytes!\n");
  703. X                        qb_term (-1);
  704. X                    }
  705. X
  706. X                    strcpy (monitor, optarg);
  707. X                    break;
  708. X        case 'n':   if (strlen(optarg) >31)
  709. X                    {
  710. X                        fprintf (stderr, "Job name longer than 31 bytes!\n");
  711. X                        qb_term (-1);
  712. X                    }
  713. X                    strcpy (jobname, optarg);
  714. X            break;
  715. X        case 'r':   notify = atoi(optarg);
  716. X                    break;
  717. X    case 's':   strcpy (shell, optarg);
  718. X            debug = 0;
  719. X            break;
  720. X        case 'v':   q_version();
  721. X    case '?':   usage (-1);
  722. X                    
  723. X    }
  724. X    if (optind >= argc)
  725. X    {
  726. X        fprintf (stderr, "Missing queue name\n");
  727. X        qb_term (-1);
  728. X    }
  729. X    queuename = argv[optind];
  730. X    strcpy (queue, QUEUEPATH);
  731. X    strcat (queue, queuename);
  732. X    qb_setterm();
  733. X    fpq = open (queue, O_RDWR);
  734. X    if (fpq == -1)
  735. X    {
  736. X        fprintf (stderr, "Invalid queue name : %s\n", queuename);
  737. X        qb_term (-1);
  738. X    }
  739. X    q_lock(fpq);
  740. X    read  (fpq, &head, sizeof(head));
  741. X    if (bad_queue()) qb_exit(-1);
  742. X    if ((head.qh_flags & qh_enabled) == 0)
  743. X    {
  744. X        fprintf (stderr, "Queue %s is not accepting entries!\n", queuename);
  745. X        qb_exit(-1);
  746. X    }
  747. X    if ((strcmp (head.qh_defmon, "NONE") == 0))
  748. X    {
  749. X        if  (*monitor == 0)
  750. X    {
  751. X        fcptr = getenv ("MONITOR");
  752. X        if (fcptr == NULL)
  753. X        {
  754. X            fprintf(stderr, "No MONITOR environment string.. cannot submit\n");
  755. X            qb_exit(-1);
  756. X        }
  757. X        strcpy (monitor, fcptr);
  758. X    }
  759. X    }
  760. X    if (*monitor != 0)
  761. X    {
  762. X        if (*monitor != '/') /* monitor should be full pathspec */
  763. X        { /* so add current working directory */
  764. X            getcwd (buff, 128);
  765. X            if (buff [strlen(buff) - 1] != '/') strcat (buff, "/");
  766. X            strcat (buff, monitor);
  767. X            strcpy (monitor, buff);
  768. X
  769. X        }
  770. X        if (strlen(monitor) > 63)
  771. X        {
  772. X            fprintf (stderr, "Monitor path > 63 characters .. aborting\n");
  773. X            qb_exit(-1);
  774. X        }
  775. X        if (access(monitor, W_OK) == 0) /* monitor path is accessible */
  776. X        {
  777. X            fp = fopen (monitor, "w");
  778. X            if (fp == NULL) /* monitor is a directory */
  779. X            {
  780. X                if (monitor [strlen(monitor) - 1] != '/')
  781. X                strcat (monitor, "/");
  782. X                strcat (monitor, queuename);
  783. X                strcat (monitor, ".mon");
  784. X            }
  785. X            else fclose (fp);
  786. X        }
  787. X        else            /* file does not exist or we don't have access */
  788. X        {
  789. X            fp = fopen (monitor, "w"); /*can we create it? */
  790. X            if (fp == NULL)
  791. X            {
  792. X                fprintf (stderr, "Invalid path for monitor: %s\n", monitor);
  793. X                qb_term (-1);
  794. X            }
  795. X            else
  796. X            {
  797. X                fclose (fp);
  798. X                unlink (monitor);
  799. X            }
  800. X        }
  801. X    }
  802. X    strcpy (temp, queuename);
  803. X    temp [4] = 0;
  804. X    strcat (temp, "XXXXXX");
  805. X    mktemp (temp);
  806. X    strcpy (buff, head.qh_spool);
  807. X    if (buff[strlen(buff) -1] != '/') strcat (buff, "/");
  808. X    strcat (buff,temp);
  809. X    jcl = temp;
  810. X    strcpy (jclfile, buff);
  811. X    fpout = fopen (buff, "w");
  812. X    if (fpout == NULL)
  813. X    {
  814. X        fprintf (stderr, "Cannot create jcl file!\n");
  815. X        qb_exit (-1);
  816. X    }
  817. X    jobuid = getuid();
  818. X    saveuid = jobuid;
  819. X    jobgid = getgid();
  820. X    savegid = jobgid;
  821. X    jcwd = getcwd (NULL, 128);
  822. X    if ((head.qh_flags & qh_fixed) == 0)
  823. X    {
  824. X        if (lflag == 0) /* not needed for link */
  825. X        {
  826. X        if (shell[0] == 0)
  827. X        {
  828. X            fprintf (fpout, "#!/bin/sh");
  829. X            if (debug != 0) fprintf (fpout, " -x\n");
  830. X            else            fprintf (fpout, "\n");
  831. X        }
  832. X        else fprintf (fpout, "#!%s\n",shell);
  833. X        /* is there an exclude environment file? */
  834. X        strcpy (buff, QUEUEPATH);
  835. X        strcat (buff, ".qxenv");
  836. X        fpin = fopen(buff, "r");
  837. X        if (fpin != NULL)
  838. X        {
  839. X            /* set up exclude environment table */
  840. X            while (fgets(buff, 256, fpin) != NULL)
  841. X            {
  842. X                if (buff[0] == '#') continue;
  843. X                if (buff[0] == ' ') continue;
  844. X                sscanf(buff, "%s", rcmd);
  845. X                add_envlist(root, rcmd);
  846. X            }
  847. X        fclose (fpin);
  848. X        }
  849. X        for (i=0; envp[i] != NULL; i++)
  850. X        {
  851. X            strcpy (buff, envp[i]);
  852. X            for (j = 0; buff[j] != '='; j++){}
  853. X            buff[j] = 0;
  854. X            if (scan_envlist(root, buff) <= 0)
  855. X            {
  856. X            fprintf(fpout, "#ENV  %s\n",  envp[i]);
  857. X            }
  858. X            if (strcmp (buff, "JOBNAME") == 0) 
  859. X            {
  860. X            if (strlen (buff) > 31) buff[31] = 0;
  861. X            if (jobname[0] == 0) strcpy (jobname, buff);
  862. X            }
  863. X        }
  864. X        fprintf (fpout, "cd %s\n", jcwd);
  865. X        if (root != (struct envlist *) NULL)
  866. X        {
  867. X            free_envlist(root);
  868. X            free (root);
  869. X        }
  870. X        }
  871. X    }
  872. X    else
  873. X    {
  874. X        if (lflag != 0)
  875. X        {
  876. X        fprintf (stderr, "Cannot use linked job in fixed context queue\n");
  877. X        qb_exit(-1);
  878. X        }
  879. X        strcpy (buff, QUEUEPATH);
  880. X        strcat (buff, ".");
  881. X        strcat (buff, queuename);
  882. X        strcat (buff, "rc");
  883. X        fpin = fopen (buff, "r");
  884. X        if (fpin == NULL)
  885. X        {
  886. X        printf ("Can't access initialisation file: %s\n", buff);
  887. X        fclose (fpout);
  888. X        unlink (jclfile);
  889. X        exit (-1);
  890. X        }
  891. X            fgets (buff, 128, fpin);  
  892. X        if ((*buff == '#') && (buff[1] == '!') && (buff[2] == '/'))
  893. X        {
  894. X        fprintf (fpout, "%s", buff);
  895. X        fgets   (buff, 128, fpin);
  896. X        }
  897. X        else
  898. X        {
  899. X        if (*shell == 0)
  900. X        {
  901. X            fprintf (fpout, "#!/bin/sh");
  902. X            if (debug != 0) fprintf (fpout, " -x\n");
  903. X            else            fprintf (fpout, "\n");
  904. X        }
  905. X        else fprintf (fpout, "#!%s\n",shell);
  906. X        }
  907. X            while (*buff != 0)  
  908. X        {
  909. X        fixedcontext = 0;
  910. X        sscanf (buff, "%s", rcmd);
  911. X        if (strcmp (rcmd, "#QCONTEXT") == 0)
  912. X        {
  913. X             fixedcontext = 1;
  914. X             /* set job uid and gid to QCONTEXT */
  915. X             i = sscanf (buff, "%s%d%d", rcmd, &gotuid, &gotgid);
  916. X             switch (i)
  917. X             {
  918. X            case 1: jobuid = saveuid;
  919. X                jobgid = savegid;
  920. X                break;
  921. X            case 2: jobgid = savegid;
  922. X                jobuid = (gotuid==0) ? saveuid : gotuid;
  923. X                break;
  924. X            case 3: jobgid = (gotgid==0) ? savegid : gotgid;
  925. X                jobuid = (gotuid==0) ? saveuid : gotuid;
  926. X                break;
  927. X             }
  928. X        }
  929. X        if (strcmp (rcmd, "#QUSERS") == 0)
  930. X        {
  931. X             fixedcontext = 1;
  932. X                     if (permission > 0) break;
  933. X             permission = 0;
  934. X             /* check uid against list of permitted id's */
  935. X             i = sscanf (buff,"%s%d%d%d%d%d%d%d%d%d%d", rcmd,
  936. X                  &qpuid[0],&qpuid[1],&qpuid[2],&qpuid[3], 
  937. X                                  &qpuid[4],&qpuid[5],&qpuid[6],&qpuid[7],
  938. X                  &qpuid[8],&qpuid[9]);
  939. X                     for (j=0; j < i; j++)
  940. X             if (qpuid[j] == saveuid) 
  941. X             {
  942. X                          permission ++;     
  943. X              break;
  944. X             }
  945. X        }
  946. X        if (strcmp (rcmd, "#QGROUPS") == 0)
  947. X        {
  948. X             fixedcontext = 1;
  949. X                     if (permission > 0) break;
  950. X             permission = 0;
  951. X             /* check gid against list of permitted id's */
  952. X             i = sscanf (buff,"%s%d%d%d%d%d%d%d%d%d%d", rcmd,
  953. X                  &qpgid[0],&qpgid[1],&qpgid[2],&qpgid[3], 
  954. X                                  &qpgid[4],&qpgid[5],&qpgid[6],&qpgid[7],
  955. X                  &qpgid[8],&qpgid[9]);
  956. X                     for (j=0; j < i; j++)
  957. X             if (qpgid[j] == savegid) 
  958. X             {
  959. X                          permission ++;     
  960. X              break;
  961. X             }
  962. X        }
  963. X        if (strcmp (rcmd, "#QGETENV") == 0)
  964. X        {
  965. X                 fixedcontext = 1;
  966. X             sscanf (buff, "%s %s", rcmd, envar);
  967. X                 if (envar == NULL) break;
  968. X             fcptr = getenv (envar);
  969. X             if (fcptr == NULL) break;
  970. X             fprintf (fpout, "#ENV  %s=%s\n",envar, fcptr);
  971. X        }
  972. X                if (fixedcontext == 0) fputs (buff, fpout);
  973. X        *buff = 0;
  974. X                fgets (buff, 128, fpin);  
  975. X        }
  976. X        if ((permission == 0) && (jobuid != 0) && (jobuid != saveuid))
  977. X        {
  978. X        puts ("User does not have permission to submit jobs to this Queue");
  979. X        puts ("please contact your system administrator");
  980. X        sprintf(buff, "echo 'Permission violation in fixed context queue %s\nby UID %d on `tty`>/dev/console", queuename, saveuid);
  981. X        system (buff);
  982. X        fclose (fpout);
  983. X        unlink (jclfile);
  984. X        exit (-1);
  985. X        }
  986. X    }
  987. X    optind ++;
  988. X    if (optind < argc)
  989. X    {
  990. X        if (argv[optind][0] != '/')
  991. X        {
  992. X            /* no absolute path given so prefix with current path */
  993. X            strcpy (buff, jcwd);
  994. X            strcat (buff,"/");
  995. X            strcat (buff, argv[optind]);
  996. X        }
  997. X        else strcpy (buff, argv[optind]);
  998. X    }
  999. X    if (lflag && (optind < argc))
  1000. X    {
  1001. X        fprintf (fpout, "#!L");
  1002. X        fprintf (fpout, "%s\n", buff);
  1003. X        if (jobname[0] == 0)
  1004. X        {
  1005. X            /* no jobname, & file linked, use filename for jobname */
  1006. X            for (i=0; (i < 30 && argv[optind][i] != 0 && argv[optind][i] != '\n'); i++) jobname[i] = argv[optind][i];
  1007. X            jobname[i] = 0;
  1008. X        }
  1009. X    }
  1010. X    else
  1011. X    {
  1012. X        if (optind >= argc) fpin = stdin;
  1013. X        else
  1014. X        {
  1015. X            fpin = fopen (buff, "r");
  1016. X            if (fpin == NULL)
  1017. X            {
  1018. X                fprintf (stderr, "Unable to read input file %s!\n", argv[optind]);
  1019. X                qb_exit (-1);
  1020. X            }
  1021. X        }
  1022. X        while (fgets (buff, 128, fpin) != NULL)
  1023. X        {
  1024. X            fputs (buff, fpout);
  1025. X            if (*jobname == 0)
  1026. X            {
  1027. X                fcptr = strrchr(buff, '\n');
  1028. X                if (fcptr != NULL) *fcptr = 0;
  1029. X                fcptr = strchr (buff, '=');
  1030. X                if (fcptr != NULL)
  1031. X                {
  1032. X                    *fcptr = 0;
  1033. X                    fcptr ++;
  1034. X                    if (strcmp (buff, "JOBNAME") == 0)
  1035. X                        strcpy (jobname, fcptr);
  1036. X                }
  1037. X            }
  1038. X        }
  1039. X        if (jobname[0] == 0)
  1040. X        {
  1041. X            /* no jobname (probably crqentry) so use last line of jcl for name */
  1042. X            for (i=0; (i < 30 && buff[i] != 0 && buff[i] != '\n'); i++) jobname[i] = buff[i];
  1043. X            jobname[i] = 0;
  1044. X        }
  1045. X    }
  1046. X    fclose (fpout);
  1047. X    if (!sflag) fclose (fpin);
  1048. X    entry.qe_uid = jobuid;
  1049. X    entry.qe_gid = jobgid;
  1050. X    chmod (jclfile, 0700);
  1051. X    chown (jclfile, entry.qe_uid, entry.qe_gid);
  1052. X    i = ++head.qh_hiwater;
  1053. X    i %= 999;
  1054. X    if (head.qh_noentries == 0) i = 1;
  1055. X    head.qh_hiwater = i;
  1056. X    entry.qe_jobno = i;
  1057. X    entry.qe_status = 0;
  1058. X    entry.qe_repcount = 0;
  1059. X    entry.qe_notify = notify;
  1060. X    entry.qe_submitted = time ((time_t *)0);
  1061. X    strcpy (entry.qe_jcl, temp);
  1062. X
  1063. X    if (jobname[0] != 0) strcpy (entry.qe_jobname, jobname);
  1064. X    if (monitor[0] != 0) strcpy (entry.qe_monitor, monitor);
  1065. X    else                 strcpy (entry.qe_monitor, "");
  1066. X    tty =  ttyname(0);
  1067. X    if (tty != NULL)
  1068. X    {
  1069. X        strcpy (buff, tty);
  1070. X        for (i = strlen(buff); buff[i] != '/'; i--){}
  1071. X        strcpy (entry.qe_tty, buff+i+1);
  1072. X    }
  1073. X    else strcpy (entry.qe_tty, "");
  1074. X    cuserid(entry.qe_uname);
  1075. X    i = head.qh_noentries ++;
  1076. X    lseek (fpq, 0, SEEK_SET);
  1077. X    write (fpq, &head, sizeof(head));
  1078. X    lseek (fpq, (sizeof(head)+(i*sizeof(entry))), SEEK_SET);
  1079. X    write (fpq, &entry, sizeof(entry));
  1080. X    q_unlock(fpq);
  1081. X    close (fpq); fpq = 0;
  1082. X    tell_qp();        /* send qp a signal */
  1083. X    printf ("Queue %s accepted entry no: %d\n", queuename, head.qh_hiwater);
  1084. X    qb_term(0);
  1085. X}
  1086. END_OF_FILE
  1087. if test 14536 -ne `wc -c <'src/js.c'`; then
  1088.     echo shar: \"'src/js.c'\" unpacked with wrong size!
  1089. fi
  1090. # end of 'src/js.c'
  1091. fi
  1092. if test -f 'src/qf.c' -a "${1}" != "-c" ; then 
  1093.   echo shar: Will not clobber existing file \"'src/qf.c'\"
  1094. else
  1095. echo shar: Extracting \"'src/qf.c'\" \(8190 characters\)
  1096. sed "s/^X//" >'src/qf.c' <<'END_OF_FILE'
  1097. X/************************************************************************/
  1098. X/*                                     */
  1099. X/* qf .. queue find. Report information about a queue                   */
  1100. X/*                                     */
  1101. X/*   Copyright (c) Vita Services 1990                                   */
  1102. X/*             (c) Vita Fibres   1990 1991                              */
  1103. X/*                                     */
  1104. X/************************************************************************/
  1105. X
  1106. X#include <time.h>
  1107. X#include <stdlib.h>
  1108. X#include "qbatch.h"
  1109. int mflag = 0, jflag = 0, qflag = 0, pflag = 0, aflag = 0,rflag = 0, sflag = 0, nflag = 0;
  1110. int lflag = 0;
  1111. char buff[128];
  1112. XFILE *fpq, *fp;
  1113. char *queuename;
  1114. char *mon, *fcptr;
  1115. int entryno = 0;
  1116. time_t now, then;
  1117. struct tm *jtimes;
  1118. int idle;
  1119. char monitor [128];
  1120. char tval[32];
  1121. void q_version()
  1122. X{
  1123. X    puts (&QbSID[5]);
  1124. X    puts ("");
  1125. X    puts (&QbCR1[5]);
  1126. X    puts (&QbCR2[5]);
  1127. X    puts ("");
  1128. X    exit(0);
  1129. X}
  1130. int bad_queue()
  1131. X{
  1132. X    if (strcmp (head.q_magic, "qBq") != 0)
  1133. X    {
  1134. X        fprintf(stderr,"%s is not a valid QBATCH queue\007\n", queuename);
  1135. X        return(-1);
  1136. X    }
  1137. X    return(0);
  1138. X}
  1139. char * print_time(val, opt)
  1140. unsigned long val;
  1141. int opt;
  1142. X{
  1143. X    int temp;
  1144. X    char sval[8];
  1145. X    *tval = 0;
  1146. X    temp = val/8640000;
  1147. X    if (temp)
  1148. X    {
  1149. X        sprintf(sval, "%d", temp);
  1150. X        strcat (tval, sval);
  1151. X        if (opt) strcat (tval, " Days ");
  1152. X        else strcat (tval, ":");
  1153. X        val%=8640000;
  1154. X    }
  1155. X    temp = val/360000;
  1156. X    if ((temp) || (*tval))
  1157. X    {
  1158. X        sprintf(sval, "%d", temp);
  1159. X        strcat (tval, sval);
  1160. X        if (opt) strcat (tval, " Hrs ");
  1161. X        else strcat (tval, ":");
  1162. X        val%=360000;
  1163. X    }
  1164. X    temp = val/6000;
  1165. X    if ((temp) || (*tval))
  1166. X    {
  1167. X        if (*tval) sprintf(sval, "%02d", temp);
  1168. X        else       sprintf(sval, "%d",   temp);
  1169. X        strcat     (tval, sval);
  1170. X        if (opt) strcat (tval, " Min ");
  1171. X        else strcat (tval, ":");
  1172. X        val%=6000;
  1173. X    }
  1174. X    temp = val/100;
  1175. X    if (*tval) sprintf(sval, "%02d", temp);
  1176. X    else       sprintf(sval, "%d",   temp);
  1177. X    strcat     (tval, sval);
  1178. X    strcat       (tval, ".");
  1179. X    temp = val%100;
  1180. X    sprintf(sval, "%02d", temp);
  1181. X    strcat     (tval, sval);
  1182. X        strcat (tval, " Sec");
  1183. X    return(tval);
  1184. X}
  1185. main (argc, argv)
  1186. int argc;
  1187. char * argv[];
  1188. X{
  1189. X    int c;
  1190. X    extern char *optarg;
  1191. X    extern int   optind;
  1192. X    while ((c = getopt (argc, argv, "ae:jlmnpqrsv")) != -1)
  1193. X    switch (c)
  1194. X    {
  1195. X        case 'q':
  1196. X            qflag ++;
  1197. X            break;
  1198. X        case 'j':
  1199. X            jflag ++;
  1200. X            break;
  1201. X        case 'l':
  1202. X            lflag ++;
  1203. X            break;
  1204. X        case 'm':
  1205. X            mflag ++;
  1206. X            break;
  1207. X        case 'p':
  1208. X            pflag ++;
  1209. X            break;
  1210. X        case 'a':
  1211. X            aflag ++;
  1212. X            break;
  1213. X        case 'r':
  1214. X            rflag ++;
  1215. X            break;
  1216. X        case 'n':
  1217. X            nflag ++;
  1218. X            break;
  1219. X        case 's':
  1220. X            sflag ++;
  1221. X            break;
  1222. X        case 'e':
  1223. X            entryno = atoi (optarg);
  1224. X            break;
  1225. X        case 'v':   q_version();
  1226. X    case '?': exit (-1);
  1227. X    }
  1228. X    if (optind >= argc)
  1229. X    {
  1230. X        fprintf (stderr, "Invalid or missing queue name!\n");
  1231. X        exit (-1);
  1232. X    }
  1233. X    queuename = argv[optind];
  1234. X    strcpy (buff, QUEUEPATH);
  1235. X    strcat (buff, queuename);
  1236. X    fpq = fopen (buff, "r");
  1237. X    if (fpq == NULL)
  1238. X    {
  1239. X        fprintf (stderr, "Invalid queue name: %s!\n",queuename);
  1240. X    fclose (fpq);
  1241. X        exit (-1);
  1242. X    }
  1243. X    fread (&head, sizeof(head), 1, fpq);
  1244. X    if (bad_queue())
  1245. X    {
  1246. X    fclose (fpq);
  1247. X    exit (-1);
  1248. X    }
  1249. X    if (lflag != 0)
  1250. X    {
  1251. X    fclose (fpq);
  1252. X        puts ("Queue   No of     Priority    Fixed   Enabled  Halted  Stopped");
  1253. X    puts ("Name    Entries    (nice)     Context\n");
  1254. X    printf("%s %6d     ", queuename, head.qh_noentries);
  1255. X    printf("%6d          ", head.qh_priority);
  1256. X    printf("%s      ",(head.qh_flags&qh_fixed)?"yes": "no ");
  1257. X    printf("%s     ",(head.qh_flags&qh_enabled)?"yes": "no ");
  1258. X    printf("%s     ",(head.qh_flags&qh_halt)?"yes": "no ");
  1259. X    printf("%s\n",   (head.qh_flags&qh_stop)?"yes": "no ");
  1260. X        exit(0);
  1261. X    }
  1262. X    if (nflag != 0)
  1263. X    {
  1264. X    printf ("%d\n", head.qh_priority);
  1265. X    fclose (fpq);
  1266. X        exit (0);
  1267. X    }
  1268. X    if (pflag != 0)
  1269. X    {
  1270. X        printf("%d\n", head.qh_pid);
  1271. X    fclose (fpq);
  1272. X        exit (0);
  1273. X    }
  1274. X    if (aflag != 0)
  1275. X    {
  1276. X        printf("%d\n", head.qh_noentries);
  1277. X    fclose (fpq);
  1278. X        exit (0);
  1279. X    }
  1280. X    if (rflag != 0)
  1281. X    {
  1282. X    if (head.qh_noentries > 0)
  1283. X    {
  1284. X        fread (&entry, sizeof(entry), 1, fpq);
  1285. X        printf("%d\n", entry.qe_status);
  1286. X    }
  1287. X    else printf("%d\n",0);
  1288. X    fclose (fpq);
  1289. X    exit (0);
  1290. X    }
  1291. X    if (sflag != 0)
  1292. X    {
  1293. X        fclose (fpq);
  1294. X        if (head.qh_proc == 0)
  1295. X        {
  1296. X        printf ("Queue has not been run\n");
  1297. X        exit (0);
  1298. X        }
  1299. X            jtimes = (struct tm *)localtime (&head.qh_proc);
  1300. X            printf ("\n Queue started     : %s" ,asctime (jtimes));
  1301. X        if (head.qh_pid == 0)
  1302. X        {
  1303. X            printf("\n Queue is not running\n");
  1304. X            }
  1305. X            else
  1306. X        {
  1307. X            now = time ((time_t *) 0);
  1308. X            then = now;
  1309. X            now -= head.qh_proc;
  1310. X            now *= 100;
  1311. X            printf ("\n Available for     : %s\n" ,print_time (now, 1));
  1312. X        }
  1313. X        if (head.qh_jobcount == 0)
  1314. X        {
  1315. X        printf("No jobs run since queue started\n");
  1316. X        exit(0);
  1317. X        }
  1318. X        printf (" No. Jobs Processed: %d\n\n", head.qh_jobcount);
  1319. X        printf ("Times:\t\t    Actual\t\t\tAv. Per Job\n\n");
  1320. X        printf ("Queued\t\t%16s", print_time(head.qh_queued, 0));
  1321. X        printf ("        %16s\n", print_time(head.qh_queued/head.qh_jobcount, 0));
  1322. X        printf ("Real\t\t%16s", print_time(head.qh_real, 0));
  1323. X        printf ("        %16s\n", print_time(head.qh_real/head.qh_jobcount, 0));
  1324. X        printf ("User\t\t%16s", print_time(head.qh_user, 0));
  1325. X        printf ("        %16s\n", print_time(head.qh_user/head.qh_jobcount, 0));
  1326. X        printf ("System\t\t%16s", print_time(head.qh_system, 0));
  1327. X        printf ("        %16s\n", print_time(head.qh_system/head.qh_jobcount, 0));
  1328. X        if (head.qh_pid == 0) exit(0);
  1329. X        head.qh_real *= 10000;
  1330. X        head.qh_real /= now ;
  1331. X            printf("\nUtilisation (real/available) %d.%02d%%\n",(head.qh_real/100), (head.qh_real%100));
  1332. X        if (head.qh_start)
  1333. X        {
  1334. X            then -= head.qh_start;
  1335. X            then *= 100;
  1336. X        printf ("\nCurrent job not accounted for above, running for : %s\n", print_time(then));
  1337. X        }
  1338. X        fclose (fpq);
  1339. X        exit(0);
  1340. X    }
  1341. X    if (qflag != 0)
  1342. X    {
  1343. X    if (strcmp (head.qh_defmon, "NONE") == 0)
  1344. X    {
  1345. X        fprintf(stderr, "%s has NO default monitor\007\n", queuename);
  1346. X        fclose (fpq);
  1347. X        exit(-1);
  1348. X    }
  1349. X    puts (head.qh_defmon);
  1350. X    }
  1351. X    else
  1352. X    {
  1353. X    if ((jflag == 0) && (mflag == 0) && (entryno == 0))
  1354. X    {
  1355. X        fprintf(stderr, "No options specified\007\n");
  1356. X        fclose (fpq);
  1357. X        exit(0);
  1358. X    }
  1359. X    if ((jflag == 0) && (mflag == 0))
  1360. X    {
  1361. X        fprintf(stderr, "Entryno specified without j or m\007\n");
  1362. X        fclose (fpq);
  1363. X        exit(0);
  1364. X    }
  1365. X        if (head.qh_noentries > 0)
  1366. X        {
  1367. X            if (entryno == 0) fread (&entry, sizeof(entry), 1, fpq);
  1368. X            else
  1369. X            {
  1370. X                entry.qe_jobno = 0;
  1371. X                while (entry.qe_jobno != entryno) 
  1372. X                {
  1373. X                    if (fread (&entry, sizeof(entry), 1, fpq) == 0)
  1374. X                    {
  1375. X                        fprintf (stderr, "entry %d does not exist\n", entryno);
  1376. X            fclose (fpq);
  1377. X                        exit (-1);
  1378. X                    }
  1379. X                }
  1380. X            }
  1381. X            if (jflag != 0) 
  1382. X            {
  1383. X                strcpy (buff, head.qh_spool);
  1384. X                if (buff[strlen(buff) -1] != '/') strcat (buff,"/");
  1385. X                strcat (buff,entry.qe_jcl);
  1386. X                puts (buff);
  1387. X            }
  1388. X            if (mflag != 0)
  1389. X            {
  1390. X                if (entry.qe_monitor[0] != 0) puts (entry.qe_monitor);
  1391. X                else
  1392. X                {
  1393. X            if (strcmp (head.qh_defmon, "NONE") == 0)
  1394. X            {
  1395. X                fprintf(stderr, "%s has NO default monitor\007\n", queuename);
  1396. X                fclose (fpq);
  1397. X                exit(-1);
  1398. X            }
  1399. X            puts (head.qh_defmon);
  1400. X                }
  1401. X            }
  1402. X        }
  1403. X        else 
  1404. X        {
  1405. X        if (mflag != 0)
  1406. X            {
  1407. X            if (strcmp (head.qh_defmon, "NONE") == 0)
  1408. X            {
  1409. X                fprintf(stderr, "%s has NO default monitor\007\n", queuename);
  1410. X                fclose (fpq);
  1411. X                exit(-1);
  1412. X            }
  1413. X            puts (head.qh_defmon);
  1414. X            }
  1415. X        else
  1416. X            {
  1417. X                fprintf (stderr, "No entries for j or m option\n");
  1418. X        fclose (fpq);
  1419. X                exit (-1);
  1420. X            }
  1421. X        }
  1422. X    }
  1423. X    fclose (fpq);
  1424. X    exit (0);
  1425. X}
  1426. END_OF_FILE
  1427. if test 8190 -ne `wc -c <'src/qf.c'`; then
  1428.     echo shar: \"'src/qf.c'\" unpacked with wrong size!
  1429. fi
  1430. # end of 'src/qf.c'
  1431. fi
  1432. echo shar: End of archive 5 \(of 6\).
  1433. cp /dev/null ark5isdone
  1434. MISSING=""
  1435. for I in 1 2 3 4 5 6 ; do
  1436.     if test ! -f ark${I}isdone ; then
  1437.     MISSING="${MISSING} ${I}"
  1438.     fi
  1439. done
  1440. if test "${MISSING}" = "" ; then
  1441.     echo You have unpacked all 6 archives.
  1442.     rm -f ark[1-9]isdone
  1443. else
  1444.     echo You still need to unpack the following archives:
  1445.     echo "        " ${MISSING}
  1446. fi
  1447. ##  End of shell archive.
  1448. exit 0
  1449.  
  1450. exit 0 # Just in case...
  1451. -- 
  1452. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1453. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1454. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1455. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1456.