home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume25
/
QBATCH
/
part05
< prev
next >
Wrap
Text File
|
1991-11-04
|
46KB
|
1,456 lines
Newsgroups: comp.sources.misc
From: alan@tharr.UUCP (Alan Saunders)
Subject: v25i024: QBATCH - a queued batch processing system for UNIX, Part05/06
Message-ID: <1991Nov5.034852.5158@sparky.imd.sterling.com>
X-Md4-Signature: c94ab58832177a5cae6e94b86d55bf1f
Date: Tue, 5 Nov 1991 03:48:52 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: alan@tharr.UUCP (Alan Saunders)
Posting-number: Volume 25, Issue 24
Archive-name: QBATCH/part05
Environment: UNIX
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 5 (of 6)."
# Contents: doc/chap.04 src/jk.c src/js.c src/qf.c
# Wrapped by root@vfib_d on Thu Oct 31 15:46:40 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'doc/chap.04' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'doc/chap.04'\"
else
echo shar: Extracting \"'doc/chap.04'\" \(10173 characters\)
sed "s/^X//" >'doc/chap.04' <<'END_OF_FILE'
X QBATCH .. a queued batch processing system for UNIX
X
X
X The QBATCH system and its related programs were
X written by Alan D. Saunders and are
X Copyright (c) Vita Services Ltd. 1990 and
X Copyright (c) Vita Fibres Ltd. 1991
X
X4. USER commands.
X
X Note: this is a descriptive text. Full details of all the QBATCH commands
X are provided in the relevant man pages. There is also a man page for QBATCH
X which contains a summary of all QBATCH commands.
X See also ADMINISTRATIVE commands.
X
X qa Queue availability. For a given user running qa, the accessibility of
X all queues is checked. All fixed context queues are checked to see if
X this user is permitted (by uid or gid) to submit jobs. All fixed
X context queues which permit this user to submit, and all open queues
X are listed with a brief (one line) description.
X viz:
X
X Queues available to alan
X
X Queue No. Priority Fixed Enabled Halted Stopped
X Name Entries (nice) Context
X
X fasq 2 -5 no yes no no
X fault 0 0 no yes no no
X fcon 14 10 yes yes no yes
X fcsq 4 5 no yes no no
X fcst 1 -5 no yes no no
X intq 0 0 no no no no
X invq 1 0 no yes no no
X mant 2 -5 no yes no no
X masq 2 -5 no yes no no
X mbsq 0 10 no no no no
X slwq 8 15 no yes no no
X sopq 4 5 no yes no no
X sopt 3 -5 no yes no no
X work 14 10 no yes no no
X
X js Job submit. This is used to submit jobs to a QBATCH queue.
X By default, a job is run under the bourne shell. This may be
X overridden by using the -s option to js, or in the case of a fixed
X context queue, by the first line of the control file. Jobs submitted
X to a queue must be valid in terms of the syntax of the shell under
X which the job is to be run. This said, jobs may consist of anything
X that can be run interactively provided they don't attempt to access
X what may be unavailable resources, in particular, the vdu of the
X submittor. If the programs, or scripts use stdout and stderr for
X output, and (redirected) stdin for input, then they can be submitted to
X a queue. Programs which attempt to open /dev/tty may fail altogether
X since QBATCH jobs do not have a controlling terminal. On some systems
X they may use /dev/console instead. (this seems to be the case in SunOS
X on SPARCstations.)
X
X js will accept the job either as a named file, or from stdin. This
X allows regularly run jobs to be set up as 'jcl' files, and submitted
X as:
X js <queuename> <jclfile>
X Alternatively, stdin can be used, either directly:
X js <queuename>
X <commands>
X [..]
X ^D
X Or as a here document:
X js <queuename> <<EOjob
X <commands>
X [..]
X EOjob
X
X If submitted as a file, the 'jcl' may be created in a script, using
X prompts, and shell parameters etc to set it up.
X
X js can also be used as the destination of a pipeline in the shell, or
X as a pipe (opened for write access) in a c program.
X
X Main options:
X
X -n <name> This provides a meaningful name for the job. It's only
X use is to give some meaning to the ql output (see
X later).
X
X -m <monitor> The monitor (combined stdout and stderr) for a job is
X normally determined automatically, either by js or qp.
X (monitors are discussed later.) This option allows a
X user to define exactly where the monitor for this job
X will be written it should be a fully specified absolute
X pathspec..
X
X -s <shell> As mentioned earlier, jobs are by default run under the
X bourne shell. If the queue is fixed context, the shell
X may be specified in the control file. This option
X allows the user to specify the shell under which this
X job will be run.
X
X -r <reply code> When the process engine has finished with a job, it
X normally silently looks for the next. The reply code,
X if non-zero causes qp to execute a script called
X jobdone, which will notify the submittor as follows:
X reply code 0 No reply.
X 1 Write a message on the submittor's tty.
X 2 Mail a message to the user.
X Any other value (or not set).. no reply.
X
X jk Job kill. This allows the user to remove a job from a queue if they
X own it. The super user may kill any or all jobs in any and all queues.
X an ordinary user may kill only jobs that they themselves submitted.
X If the job is actually running, jk will refuse to remove the job unless
X the -k option is specified.
X
X jm Job monitor. This allows the addition of a monitor spec (see js) as an
X afterthought.
X
X jn Job name. Allows the addition of a job name as an afterthought.
X
X jr Job repeat. This allows the current job being processed to be
X repeated. If the -k option is used, the repeat flag will be set, and
X the job will be repeated. This allows for example, a print job
X printing on the wrong stationary to be restarted.
X
X jj Job jump. NB. This does not allow ANYBODY to jump the queue!
X This allows any user to re- order a consecutive group of their own jobs
X in a queue, by jumping a job above an adjacent prior job owned by the
X same user. Only the administrator is permitted to jump jobs above
X those with different owner id's.
X No job may be jumped above a currently running job.
X
X ql Queue list. List the contents and status of a QBATCH queue.
X The queue header data and flags are displayed, along with a line for
X each job currently in the queue. The data are more meaningful if job
X names are used when the jobs are submitted.
X viz:
X
X Status of : work
X Spooling in : /var/spool/batch/
X Monitor is : /var/spool/batch/work.mon
X Priority is : 10
X Queue last started : 12/09/91 09:02:37
X Current job started : 2/10/91 14:54:30
X
X No of Active Queue Job Job Queue Queue
X Entries (pid) Accepting Repeated Killed Halted Stopped
X 13 428 Yes No No No No
X
X 2 569 root ttyp0 2/10/91 14:55:10 UUCP Log Analysis
X 3 andy tty01 2/10/91 14:59:29 Sales Report
X 4 root console 2/10/91 15:01:00 Security Check
X 5 accounts ttyh3 2/10/91 15:03:20 Statements Print
X 6 jmajor tty0a 2/10/91 15:05:31 COBOL compile
X 7 bfrances ttyp3 2/10/91 15:05:31 exit 0
X 8 james ttyc 2/10/91 15:07:32 find ./ -name core -ls
X 9 james ttyc 2/10/91 15:08:12 test run 1
X 10 andy tty01 2/10/91 15:08:34 Invoice Print
X 11 root ttyp0 2/10/91 15:10:04 Offline Backup
X 12 accounts ttyh3 2/10/91 15:10:17 Overdue list
X 13 prog1 ttypb 2/10/91 15:11:35 make emacs
X 14 jmajor tty0a 2/10/91 15:11:36 cobrun update.cbl
X
X The output of 'ql' is in three parts:
X
X a. At the top is the basic information about the queue itself. The
X name, which files it uses, it's priority, etc.
X
X b. The next part shows the current status of the queue header flags
X and fields, which are self explanatory. The field headed 'Active'
X in this case contains the pid of the queue process engine ('qp')
X which is handling this queue. If the queue was idle (no process
X engine) this field would contain "No".
X
X c. The bulk of the output consists of a list of the entries in the
X queue, each starting with the entry number. It is this number
X which is used to manipulate individual entries in the queue
X (e.g. jk -e <entryno> <queuename> to kill (remove) a job).
X
X The next column is only ever used for the first entry in a queue,
X and only then if the queue is active. The first entry in the queue
X is the currently running entry, and this field contains the pid of
X the forked child.
X
X Column 3 is the user who submitted the job.
X
X Column 4 is the tty from which the job was submitted.
X
X Columns 5 & 6 are the date & time that the job was submitted.
X
X Column 7 is the job name, which, if used, gives some indication
X of the job running.
X
X qf Queue find.
X qt Queue test. These programs are primarily provided for use in shell
X scripts. All of the options of qf provide output on stdout relating to
X the contents and status of a queue. Most of the options to qt cause it
X to either fail, or not fail depending on the settings of the queue
X flags. The exception is the -l option which is used in the qa script
X to check the accessibility of a queue, and output the one line
X description.
X Examine the scripts rc.QBATCH and qa for examples of their use.
X
X Those options to qf which are useful interactively are:
X -m Monitor. qf returns the full absolute pathspec of the monitor
X used by the queue (see also MONITORS). So to check the progress
X of a job, the user can use:
X more `qf -m <queuename>`
X
X -l Provides a one line status report similar to qt -l but with the
X columns headed.
X
X -j jcl. returns the full absolute pathspec of the jcl file created by
X js for this job.
X
X -s Summary timings. qp maintains a limited profile timing summary for
X jobs processed in each queue. The timings for each job are written
X to the monitor, but qf -s will display the summary viz:
X
X
X Queue started : Wed Oct 2 15:02:37 1991
X
X Available for : 5 Min 14.00 Sec
X No. Jobs Processed: 10
X
X Times: Actual Av. Per Job
X
X Queued 5:45.00 Sec 34.50 Sec
X Real 1:43.68 Sec 10.36 Sec
X User 0.60 Sec 0.06 Sec
X System 2.69 Sec 0.26 Sec
X
X Utilisation (real/available) 33.01%
X
X Current job not accounted for above, running for : 7.00 Sec
X
X The figures are:
X Queued: The time a job was on the queue before starting to process.
X Real: The actual (wall clock) time from start to end of processing.
X User: The user cpu time taken by the job.
X System: The system cpu time taken by the job.
X
END_OF_FILE
if test 10173 -ne `wc -c <'doc/chap.04'`; then
echo shar: \"'doc/chap.04'\" unpacked with wrong size!
fi
# end of 'doc/chap.04'
fi
if test -f 'src/jk.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/jk.c'\"
else
echo shar: Extracting \"'src/jk.c'\" \(8327 characters\)
sed "s/^X//" >'src/jk.c' <<'END_OF_FILE'
X/************************************************************************/
X/* */
X/* jk .. Job kill. remove a job from this queue (optionally kill it). */
X/* */
X/* usage: jk [-k] [-a] [-u <userid>] [-e <entryno>] qname */
X/* */
X/* Copyright (c) Vita Services 1990 */
X/* (c) Vita Fibres 1990 1991 */
X/* */
X/************************************************************************/
X
X#include "qbatch.h"
int fpq = 0;
int i, l;
int killed = 0;
long j, k;
int aflag = 0, kflag = 0, entryno = 0;
pid_t jpid = 0;
uid_t userid = 0, uid;
off_t *entries;
char *queuename;
char queue[128];
char buff [128];
X#include "config.h"
X
X
main (argc, argv, envp)
int argc;
char *argv[], *envp[];
X{
X int c;
X extern char *optarg;
X extern int optind;
X if (argc == 1)
X {
X puts ("Usage: jk [-a] [-u <userid>] [-e <entryno>] qname");
X qb_term (0);
X }
X while ((c = getopt (argc, argv, "kau:e:v")) != -1)
X switch (c)
X {
X case 'a': aflag ++;
X break;
X case 'u': userid = atoi(optarg);
X break;
X case 'v': q_version();
X case 'k': kflag ++;
X break;
X case 'e': entryno = atoi(optarg);
X break;
X case '?': qb_term (-1);
X }
X if (optind >= argc)
X {
X fprintf (stderr, "Missing queue name\n");
X qb_term (-1);
X }
X if ((aflag !=0) && (entryno != 0))
X {
X fprintf (stderr, "-a (ALL) flag and -e (entry number) incompatible\n");
X qb_exit (-1);
X }
X uid = getuid();
X if ((aflag ==0) && (entryno == 0))
X {
X if (uid == 0) kflag = 999;
X else
X {
X fprintf (stderr, "Must have one of -a (ALL) flag or -e (entry number)\n");
X qb_exit (-1);
X }
X }
X
X queuename = argv[optind];
X strcpy (queue, QUEUEPATH);
X strcat (queue, queuename);
X qb_setterm();
X fpq = open (queue, O_RDWR);
X if (fpq == -1)
X {
X fprintf (stderr, "Invalid queue name: %s\n", queuename);
X qb_term (-1);
X }
X
X q_lock(fpq);
X read (fpq, &head, sizeof(head));
X if (bad_queue()) qb_exit(-1);
X if (head.qh_noentries == 0)
X {
X fprintf (stderr, " Queue %s is empty!\n", queuename);
X qb_term (-1);
X }
X if (uid != 0)
X {
X if ((userid != uid)&&(userid != 0) && (aflag == 0))
X {
X fprintf (stderr, "Must be super user to kill another's jobs)\n");
X qb_term (-1);
X }
X }
X if (kflag == 999)
X {
X if ((head.qh_flags & qh_kill) == 0) head.qh_flags += qh_kill;
X lseek (fpq, 0, SEEK_SET);
X write (fpq, &head, sizeof(head));
X q_unlock(fpq);
X close (fpq);fpq = 0;
X tell_qp();
X qb_exit (0);
X }
X if ((head.qh_flags&qh_halt) == 0)
X {
X head.qh_flags += qh_halt;
X lseek (fpq, 0, SEEK_SET);
X write (fpq, &head, sizeof(head));
X q_unlock(fpq);
X close (fpq);fpq = 0;
X tell_qp();
X }
X do
X {
X fpq = open (queue, O_RDWR);
X q_lock(fpq);
X read (fpq, &head, sizeof(head));
X read (fpq, &entry, sizeof(entry));
X jpid = entry.qe_status;
X if (jpid != 0) /* something running */
X {
X q_unlock(fpq);
X close (fpq);fpq = 0;
X fpq = open (queue, O_RDWR);
X q_lock(fpq);
X read (fpq, &head, sizeof(head));
X if (head.qh_noentries == 0)
X {
X fprintf (stderr, " Queue %s is empty!\n", queuename);
X qb_term (-1);
X }
X read (fpq, &entry, sizeof(entry));
X if ((entry.qe_status != jpid) && (jpid != 0)) /* job has changed */
X {
X jpid = 0; /* don't kill */
X }
X }
X }
X while (jpid != entry.qe_status) ;
X /* the current job is halted */
X if (jpid == 0) kflag = 0; /* nowt running, no need to kill */
X if ((uid != 0) && (uid != entry.qe_uid) && (aflag == 0))
X {
X fprintf (stderr, "Must be super user to kill another's jobs)\n");
X lseek (fpq, 0, SEEK_SET);
X if ((head.qh_flags & qh_halt) != 0)
X {
X head.qh_flags -= qh_halt;
X }
X write (fpq, &head, sizeof(head));
X qb_exit (-1);
X }
X
X entries = (off_t *) calloc ((head.qh_noentries+1), sizeof(off_t));
X lseek (fpq, sizeof(head), SEEK_SET);
X l = 0;
X for (i = 0; i < head.qh_noentries; i++)
X {
X j = lseek (fpq, 0L, SEEK_CUR);
X read (fpq, &entry, sizeof(entry));
X if ((uid == 0) || (uid == entry.qe_uid)) /* we can kill it */
X {
X if (aflag) /* kill all */
X {
X if ((uid == 0) && (userid == entry.qe_uid))
X { /* we don't want this */
X killed++;
X strcpy (buff, head.qh_spool);
X if (buff[strlen(buff) -1] != '/') strcat (buff, "/");
X strcat (buff, entry.qe_jcl);
X if (entry.qe_status == 0) unlink (buff);
X continue;
X }
X if (userid == 0)
X {
X if (uid == entry.qe_uid)
X { /* or this */
X killed ++;
X strcpy (buff, head.qh_spool);
X if (buff[strlen(buff) -1] != '/') strcat (buff, "/");
X strcat (buff, entry.qe_jcl);
X if (entry.qe_status == 0) unlink (buff);
X continue;
X }
X if (uid == 0)
X { /* or this */
X killed ++;
X strcpy (buff, head.qh_spool);
X if (buff[strlen(buff) -1] != '/') strcat (buff, "/");
X strcat (buff, entry.qe_jcl);
X if (entry.qe_status == 0) unlink (buff);
X continue;
X }
X }
X }
X else
X { /* just a given entry */
X if (entry.qe_jobno == entryno)
X
X { /* or this */
X killed ++;
X strcpy (buff, head.qh_spool);
X if (buff[strlen(buff) -1] != '/') strcat (buff, "/");
X strcat (buff, entry.qe_jcl);
X if (entry.qe_status == 0)
X {
X unlink (buff);
X kflag = 0;
X }
X continue;
X }
X }
X }
X entries[l] = j; /* we must want it */
X l++;
X }
X /* we now have a table (entries) containing the offsets of those wanted */
X k = lseek (fpq, sizeof(head), SEEK_SET);
X head.qh_noentries = 0;
X if (k != entries[0])
X { /* we don't want the first entry */
X if (jpid != 0) /* job running so qp must cancel */
X {
X read (fpq, &entry, sizeof(entry)); /* skip first */
X if (kflag == 0)
X {
X printf ("Kill option not requested .. running entry not killed!\n");
X killed --;
X }
X head.qh_noentries ++;
X }
X }
X i = 0;
X while (entries[i] != 0)
X {
X k = lseek (fpq, 0L, SEEK_CUR); /* write offset */
X lseek (fpq, entries[i], SEEK_SET); /* read offset */
X read (fpq, &entry, sizeof(entry));
X lseek (fpq, k, SEEK_SET);
X write (fpq, &entry, sizeof(entry));
X head.qh_noentries ++;
X i++;
X }
X k = lseek (fpq, 0L, SEEK_CUR);
X lseek (fpq, 0, SEEK_SET);
X if ((head.qh_flags & qh_halt) != 0)
X {
X head.qh_flags -= qh_halt;
X }
X if (killed == 0) kflag = 0;
X if ((head.qh_flags & qh_kill) == 0)
X {
X if (kflag != 0) head.qh_flags += qh_kill;
X }
X write (fpq, &head, sizeof(head));
X ftruncate(fpq, k);
X /* right, now either kill or continue first entry (if running) */
X q_unlock(fpq);
X close (fpq);fpq = 0;
X tell_qp();
X printf ("Queue %s, %d entries killed\n", queuename, killed);
X exit (0);
X}
X
END_OF_FILE
if test 8327 -ne `wc -c <'src/jk.c'`; then
echo shar: \"'src/jk.c'\" unpacked with wrong size!
fi
# end of 'src/jk.c'
fi
if test -f 'src/js.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/js.c'\"
else
echo shar: Extracting \"'src/js.c'\" \(14536 characters\)
sed "s/^X//" >'src/js.c' <<'END_OF_FILE'
X/************************************************************************/
X/* */
X/* js .. job submit. submit a job to an existing queue. */
X/* */
X/* Usage js [-l] [-d] [-r<replycode>] [-m<monitor>] [-n<jobname>] */
X/* queuename [<jclfile>] */
X/* */
X/* Copyright (c) Vita Services 1990 */
X/* (c) Vita Fibres 1990 1991 */
X/* */
X/************************************************************************/
X
X#include "qbatch.h"
X#include <stdlib.h>
X#include <malloc.h>
int fpq = 0;
XFILE *fpin, *fpout, *fp;
char temp [16], *jcl, *jcwd = NULL;
int i,j,k, debug = 0;
int qpuid[10];
int qpgid[10];
int lflag = 0, sflag = 0, fixedcontext = 0, permission = -1;
int gotuid, gotgid;
uid_t jobuid, saveuid, testuid;
gid_t jobgid, savegid;
int envcount = 0;
int notify = 0;
char envar[64];
char *fcptr;
char shell [64] = "";
char monitor[64] = "";
char jobname[32];
char *tty;
char *queuename;
char jclfile[128];
char queue[128];
char buff [256];
char rcmd [128];
struct envlist {
X char *envptr;
X struct envlist *left;
X struct envlist *right;
X };
struct envlist *root = (struct envlist *) NULL;
X#include "config.h"
int scan_envlist (ptr, str)
struct envlist *ptr;
char *str;
X{
X int found;
X if (ptr == (struct envlist*) NULL) return (0);
X found = strcmp (str, ptr->envptr);
X if (found < 0) return (scan_envlist(ptr->left, str));
X if (found == 0) return (1);
X return (scan_envlist(ptr->right, str));
X}
int free_envlist (ptr)
struct envlist *ptr;
X{
X if (ptr == (struct envlist *) NULL) return;
X if (ptr->left != (struct envlist *) NULL)
X {
X (free_envlist(ptr->left));
X free (ptr->left);
X }
X if (ptr->right != (struct envlist *) NULL)
X {
X (free_envlist(ptr->right));
X free (ptr->right);
X }
X}
X
int add_envlist (ptr, str)
struct envlist *ptr;
char *str;
X{
X int found;
X if (ptr == (struct envlist *) NULL)
X {
X if (ptr != root) return (-1);
X ptr = (struct envlist *) malloc (sizeof(struct envlist));
X ptr->envptr = malloc(strlen(str)+1);
X strcpy (ptr->envptr, str);
X ptr->left = (struct envlist *) NULL;
X ptr->right = (struct envlist *) NULL;
X root = ptr;
X return (1);
X
X }
X found = strcmp (str, ptr->envptr);
X if (found < 0)
X {
X if (ptr->left == (struct envlist *) NULL)
X {
X ptr->left = (struct envlist *) malloc (sizeof(struct envlist));
X ptr->left->envptr = malloc(strlen(str)+1);
X strcpy (ptr->left->envptr, str);
X ptr->left->left = (struct envlist *) NULL;
X ptr->left->right = (struct envlist *) NULL;
X return (1);
X }
X else
X return (add_envlist (ptr->left, str));
X }
X if (found == 0) return (0); /* already in list */
X if (ptr->right == (struct envlist *) NULL)
X {
X ptr->right = (struct envlist *) malloc (sizeof(struct envlist));
X ptr->right->envptr = malloc(strlen(str)+1);
X strcpy (ptr->right->envptr, str);
X ptr->right->left = (struct envlist *) NULL;
X ptr->right->right = (struct envlist *) NULL;
X return (1);
X }
X else
X return (add_envlist (ptr->right, str));
X}
X
void usage(i)
int i;
X{
X puts ("Usage: js [-r<replycode>] [-m<monitor>] [-n<jobname>] [-s <shell>] queuename [<jclfile>]");
X qb_term (i);
X}
main (argc, argv, envp)
int argc;
char *argv[], *envp[];
X{
X int c;
X extern char *optarg;
X extern int optind;
X if (argc == 1) usage (0);
X while ((c = getopt (argc, argv, "dlm:n:r:s:v")) != -1)
X switch (c)
X {
X case 'd': if (shell[0] == 0) debug ++;
X break;
X case 'l': lflag ++;
X break;
X case 'm': if (strlen(optarg) >63)
X {
X fprintf (stderr, "Monitor path longer than 63 bytes!\n");
X qb_term (-1);
X }
X
X strcpy (monitor, optarg);
X break;
X case 'n': if (strlen(optarg) >31)
X {
X fprintf (stderr, "Job name longer than 31 bytes!\n");
X qb_term (-1);
X }
X strcpy (jobname, optarg);
X break;
X case 'r': notify = atoi(optarg);
X break;
X case 's': strcpy (shell, optarg);
X debug = 0;
X break;
X case 'v': q_version();
X case '?': usage (-1);
X
X }
X if (optind >= argc)
X {
X fprintf (stderr, "Missing queue name\n");
X qb_term (-1);
X }
X queuename = argv[optind];
X strcpy (queue, QUEUEPATH);
X strcat (queue, queuename);
X qb_setterm();
X fpq = open (queue, O_RDWR);
X if (fpq == -1)
X {
X fprintf (stderr, "Invalid queue name : %s\n", queuename);
X qb_term (-1);
X }
X q_lock(fpq);
X read (fpq, &head, sizeof(head));
X if (bad_queue()) qb_exit(-1);
X if ((head.qh_flags & qh_enabled) == 0)
X {
X fprintf (stderr, "Queue %s is not accepting entries!\n", queuename);
X qb_exit(-1);
X }
X if ((strcmp (head.qh_defmon, "NONE") == 0))
X {
X if (*monitor == 0)
X {
X fcptr = getenv ("MONITOR");
X if (fcptr == NULL)
X {
X fprintf(stderr, "No MONITOR environment string.. cannot submit\n");
X qb_exit(-1);
X }
X strcpy (monitor, fcptr);
X }
X }
X if (*monitor != 0)
X {
X if (*monitor != '/') /* monitor should be full pathspec */
X { /* so add current working directory */
X getcwd (buff, 128);
X if (buff [strlen(buff) - 1] != '/') strcat (buff, "/");
X strcat (buff, monitor);
X strcpy (monitor, buff);
X
X }
X if (strlen(monitor) > 63)
X {
X fprintf (stderr, "Monitor path > 63 characters .. aborting\n");
X qb_exit(-1);
X }
X if (access(monitor, W_OK) == 0) /* monitor path is accessible */
X {
X fp = fopen (monitor, "w");
X if (fp == NULL) /* monitor is a directory */
X {
X if (monitor [strlen(monitor) - 1] != '/')
X strcat (monitor, "/");
X strcat (monitor, queuename);
X strcat (monitor, ".mon");
X }
X else fclose (fp);
X }
X else /* file does not exist or we don't have access */
X {
X fp = fopen (monitor, "w"); /*can we create it? */
X if (fp == NULL)
X {
X fprintf (stderr, "Invalid path for monitor: %s\n", monitor);
X qb_term (-1);
X }
X else
X {
X fclose (fp);
X unlink (monitor);
X }
X }
X }
X strcpy (temp, queuename);
X temp [4] = 0;
X strcat (temp, "XXXXXX");
X mktemp (temp);
X strcpy (buff, head.qh_spool);
X if (buff[strlen(buff) -1] != '/') strcat (buff, "/");
X strcat (buff,temp);
X jcl = temp;
X strcpy (jclfile, buff);
X fpout = fopen (buff, "w");
X if (fpout == NULL)
X {
X fprintf (stderr, "Cannot create jcl file!\n");
X qb_exit (-1);
X }
X jobuid = getuid();
X saveuid = jobuid;
X jobgid = getgid();
X savegid = jobgid;
X jcwd = getcwd (NULL, 128);
X if ((head.qh_flags & qh_fixed) == 0)
X {
X if (lflag == 0) /* not needed for link */
X {
X if (shell[0] == 0)
X {
X fprintf (fpout, "#!/bin/sh");
X if (debug != 0) fprintf (fpout, " -x\n");
X else fprintf (fpout, "\n");
X }
X else fprintf (fpout, "#!%s\n",shell);
X /* is there an exclude environment file? */
X strcpy (buff, QUEUEPATH);
X strcat (buff, ".qxenv");
X fpin = fopen(buff, "r");
X if (fpin != NULL)
X {
X /* set up exclude environment table */
X while (fgets(buff, 256, fpin) != NULL)
X {
X if (buff[0] == '#') continue;
X if (buff[0] == ' ') continue;
X sscanf(buff, "%s", rcmd);
X add_envlist(root, rcmd);
X }
X fclose (fpin);
X }
X for (i=0; envp[i] != NULL; i++)
X {
X strcpy (buff, envp[i]);
X for (j = 0; buff[j] != '='; j++){}
X buff[j] = 0;
X if (scan_envlist(root, buff) <= 0)
X {
X fprintf(fpout, "#ENV %s\n", envp[i]);
X }
X if (strcmp (buff, "JOBNAME") == 0)
X {
X if (strlen (buff) > 31) buff[31] = 0;
X if (jobname[0] == 0) strcpy (jobname, buff);
X }
X }
X fprintf (fpout, "cd %s\n", jcwd);
X if (root != (struct envlist *) NULL)
X {
X free_envlist(root);
X free (root);
X }
X }
X }
X else
X {
X if (lflag != 0)
X {
X fprintf (stderr, "Cannot use linked job in fixed context queue\n");
X qb_exit(-1);
X }
X strcpy (buff, QUEUEPATH);
X strcat (buff, ".");
X strcat (buff, queuename);
X strcat (buff, "rc");
X fpin = fopen (buff, "r");
X if (fpin == NULL)
X {
X printf ("Can't access initialisation file: %s\n", buff);
X fclose (fpout);
X unlink (jclfile);
X exit (-1);
X }
X fgets (buff, 128, fpin);
X if ((*buff == '#') && (buff[1] == '!') && (buff[2] == '/'))
X {
X fprintf (fpout, "%s", buff);
X fgets (buff, 128, fpin);
X }
X else
X {
X if (*shell == 0)
X {
X fprintf (fpout, "#!/bin/sh");
X if (debug != 0) fprintf (fpout, " -x\n");
X else fprintf (fpout, "\n");
X }
X else fprintf (fpout, "#!%s\n",shell);
X }
X while (*buff != 0)
X {
X fixedcontext = 0;
X sscanf (buff, "%s", rcmd);
X if (strcmp (rcmd, "#QCONTEXT") == 0)
X {
X fixedcontext = 1;
X /* set job uid and gid to QCONTEXT */
X i = sscanf (buff, "%s%d%d", rcmd, &gotuid, &gotgid);
X switch (i)
X {
X case 1: jobuid = saveuid;
X jobgid = savegid;
X break;
X case 2: jobgid = savegid;
X jobuid = (gotuid==0) ? saveuid : gotuid;
X break;
X case 3: jobgid = (gotgid==0) ? savegid : gotgid;
X jobuid = (gotuid==0) ? saveuid : gotuid;
X break;
X }
X }
X if (strcmp (rcmd, "#QUSERS") == 0)
X {
X fixedcontext = 1;
X if (permission > 0) break;
X permission = 0;
X /* check uid against list of permitted id's */
X i = sscanf (buff,"%s%d%d%d%d%d%d%d%d%d%d", rcmd,
X &qpuid[0],&qpuid[1],&qpuid[2],&qpuid[3],
X &qpuid[4],&qpuid[5],&qpuid[6],&qpuid[7],
X &qpuid[8],&qpuid[9]);
X for (j=0; j < i; j++)
X if (qpuid[j] == saveuid)
X {
X permission ++;
X break;
X }
X }
X if (strcmp (rcmd, "#QGROUPS") == 0)
X {
X fixedcontext = 1;
X if (permission > 0) break;
X permission = 0;
X /* check gid against list of permitted id's */
X i = sscanf (buff,"%s%d%d%d%d%d%d%d%d%d%d", rcmd,
X &qpgid[0],&qpgid[1],&qpgid[2],&qpgid[3],
X &qpgid[4],&qpgid[5],&qpgid[6],&qpgid[7],
X &qpgid[8],&qpgid[9]);
X for (j=0; j < i; j++)
X if (qpgid[j] == savegid)
X {
X permission ++;
X break;
X }
X }
X if (strcmp (rcmd, "#QGETENV") == 0)
X {
X fixedcontext = 1;
X sscanf (buff, "%s %s", rcmd, envar);
X if (envar == NULL) break;
X fcptr = getenv (envar);
X if (fcptr == NULL) break;
X fprintf (fpout, "#ENV %s=%s\n",envar, fcptr);
X }
X if (fixedcontext == 0) fputs (buff, fpout);
X *buff = 0;
X fgets (buff, 128, fpin);
X }
X if ((permission == 0) && (jobuid != 0) && (jobuid != saveuid))
X {
X puts ("User does not have permission to submit jobs to this Queue");
X puts ("please contact your system administrator");
X sprintf(buff, "echo 'Permission violation in fixed context queue %s\nby UID %d on `tty`>/dev/console", queuename, saveuid);
X system (buff);
X fclose (fpout);
X unlink (jclfile);
X exit (-1);
X }
X }
X optind ++;
X if (optind < argc)
X {
X if (argv[optind][0] != '/')
X {
X /* no absolute path given so prefix with current path */
X strcpy (buff, jcwd);
X strcat (buff,"/");
X strcat (buff, argv[optind]);
X }
X else strcpy (buff, argv[optind]);
X }
X if (lflag && (optind < argc))
X {
X fprintf (fpout, "#!L");
X fprintf (fpout, "%s\n", buff);
X if (jobname[0] == 0)
X {
X /* no jobname, & file linked, use filename for jobname */
X for (i=0; (i < 30 && argv[optind][i] != 0 && argv[optind][i] != '\n'); i++) jobname[i] = argv[optind][i];
X jobname[i] = 0;
X }
X }
X else
X {
X if (optind >= argc) fpin = stdin;
X else
X {
X fpin = fopen (buff, "r");
X if (fpin == NULL)
X {
X fprintf (stderr, "Unable to read input file %s!\n", argv[optind]);
X qb_exit (-1);
X }
X }
X while (fgets (buff, 128, fpin) != NULL)
X {
X fputs (buff, fpout);
X if (*jobname == 0)
X {
X fcptr = strrchr(buff, '\n');
X if (fcptr != NULL) *fcptr = 0;
X fcptr = strchr (buff, '=');
X if (fcptr != NULL)
X {
X *fcptr = 0;
X fcptr ++;
X if (strcmp (buff, "JOBNAME") == 0)
X strcpy (jobname, fcptr);
X }
X }
X }
X if (jobname[0] == 0)
X {
X /* no jobname (probably crqentry) so use last line of jcl for name */
X for (i=0; (i < 30 && buff[i] != 0 && buff[i] != '\n'); i++) jobname[i] = buff[i];
X jobname[i] = 0;
X }
X }
X fclose (fpout);
X if (!sflag) fclose (fpin);
X entry.qe_uid = jobuid;
X entry.qe_gid = jobgid;
X chmod (jclfile, 0700);
X chown (jclfile, entry.qe_uid, entry.qe_gid);
X i = ++head.qh_hiwater;
X i %= 999;
X if (head.qh_noentries == 0) i = 1;
X head.qh_hiwater = i;
X entry.qe_jobno = i;
X entry.qe_status = 0;
X entry.qe_repcount = 0;
X entry.qe_notify = notify;
X entry.qe_submitted = time ((time_t *)0);
X strcpy (entry.qe_jcl, temp);
X
X if (jobname[0] != 0) strcpy (entry.qe_jobname, jobname);
X if (monitor[0] != 0) strcpy (entry.qe_monitor, monitor);
X else strcpy (entry.qe_monitor, "");
X tty = ttyname(0);
X if (tty != NULL)
X {
X strcpy (buff, tty);
X for (i = strlen(buff); buff[i] != '/'; i--){}
X strcpy (entry.qe_tty, buff+i+1);
X }
X else strcpy (entry.qe_tty, "");
X cuserid(entry.qe_uname);
X i = head.qh_noentries ++;
X lseek (fpq, 0, SEEK_SET);
X write (fpq, &head, sizeof(head));
X lseek (fpq, (sizeof(head)+(i*sizeof(entry))), SEEK_SET);
X write (fpq, &entry, sizeof(entry));
X q_unlock(fpq);
X close (fpq); fpq = 0;
X tell_qp(); /* send qp a signal */
X printf ("Queue %s accepted entry no: %d\n", queuename, head.qh_hiwater);
X qb_term(0);
X}
END_OF_FILE
if test 14536 -ne `wc -c <'src/js.c'`; then
echo shar: \"'src/js.c'\" unpacked with wrong size!
fi
# end of 'src/js.c'
fi
if test -f 'src/qf.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/qf.c'\"
else
echo shar: Extracting \"'src/qf.c'\" \(8190 characters\)
sed "s/^X//" >'src/qf.c' <<'END_OF_FILE'
X/************************************************************************/
X/* */
X/* qf .. queue find. Report information about a queue */
X/* */
X/* Copyright (c) Vita Services 1990 */
X/* (c) Vita Fibres 1990 1991 */
X/* */
X/************************************************************************/
X
X#include <time.h>
X#include <stdlib.h>
X#include "qbatch.h"
int mflag = 0, jflag = 0, qflag = 0, pflag = 0, aflag = 0,rflag = 0, sflag = 0, nflag = 0;
int lflag = 0;
char buff[128];
XFILE *fpq, *fp;
char *queuename;
char *mon, *fcptr;
int entryno = 0;
time_t now, then;
struct tm *jtimes;
int idle;
char monitor [128];
char tval[32];
void q_version()
X{
X puts (&QbSID[5]);
X puts ("");
X puts (&QbCR1[5]);
X puts (&QbCR2[5]);
X puts ("");
X exit(0);
X}
int bad_queue()
X{
X if (strcmp (head.q_magic, "qBq") != 0)
X {
X fprintf(stderr,"%s is not a valid QBATCH queue\007\n", queuename);
X return(-1);
X }
X return(0);
X}
char * print_time(val, opt)
unsigned long val;
int opt;
X{
X int temp;
X char sval[8];
X *tval = 0;
X temp = val/8640000;
X if (temp)
X {
X sprintf(sval, "%d", temp);
X strcat (tval, sval);
X if (opt) strcat (tval, " Days ");
X else strcat (tval, ":");
X val%=8640000;
X }
X temp = val/360000;
X if ((temp) || (*tval))
X {
X sprintf(sval, "%d", temp);
X strcat (tval, sval);
X if (opt) strcat (tval, " Hrs ");
X else strcat (tval, ":");
X val%=360000;
X }
X temp = val/6000;
X if ((temp) || (*tval))
X {
X if (*tval) sprintf(sval, "%02d", temp);
X else sprintf(sval, "%d", temp);
X strcat (tval, sval);
X if (opt) strcat (tval, " Min ");
X else strcat (tval, ":");
X val%=6000;
X }
X temp = val/100;
X if (*tval) sprintf(sval, "%02d", temp);
X else sprintf(sval, "%d", temp);
X strcat (tval, sval);
X strcat (tval, ".");
X temp = val%100;
X sprintf(sval, "%02d", temp);
X strcat (tval, sval);
X strcat (tval, " Sec");
X return(tval);
X}
main (argc, argv)
int argc;
char * argv[];
X{
X int c;
X extern char *optarg;
X extern int optind;
X while ((c = getopt (argc, argv, "ae:jlmnpqrsv")) != -1)
X switch (c)
X {
X case 'q':
X qflag ++;
X break;
X case 'j':
X jflag ++;
X break;
X case 'l':
X lflag ++;
X break;
X case 'm':
X mflag ++;
X break;
X case 'p':
X pflag ++;
X break;
X case 'a':
X aflag ++;
X break;
X case 'r':
X rflag ++;
X break;
X case 'n':
X nflag ++;
X break;
X case 's':
X sflag ++;
X break;
X case 'e':
X entryno = atoi (optarg);
X break;
X case 'v': q_version();
X case '?': exit (-1);
X }
X if (optind >= argc)
X {
X fprintf (stderr, "Invalid or missing queue name!\n");
X exit (-1);
X }
X queuename = argv[optind];
X strcpy (buff, QUEUEPATH);
X strcat (buff, queuename);
X fpq = fopen (buff, "r");
X if (fpq == NULL)
X {
X fprintf (stderr, "Invalid queue name: %s!\n",queuename);
X fclose (fpq);
X exit (-1);
X }
X fread (&head, sizeof(head), 1, fpq);
X if (bad_queue())
X {
X fclose (fpq);
X exit (-1);
X }
X if (lflag != 0)
X {
X fclose (fpq);
X puts ("Queue No of Priority Fixed Enabled Halted Stopped");
X puts ("Name Entries (nice) Context\n");
X printf("%s %6d ", queuename, head.qh_noentries);
X printf("%6d ", head.qh_priority);
X printf("%s ",(head.qh_flags&qh_fixed)?"yes": "no ");
X printf("%s ",(head.qh_flags&qh_enabled)?"yes": "no ");
X printf("%s ",(head.qh_flags&qh_halt)?"yes": "no ");
X printf("%s\n", (head.qh_flags&qh_stop)?"yes": "no ");
X exit(0);
X }
X if (nflag != 0)
X {
X printf ("%d\n", head.qh_priority);
X fclose (fpq);
X exit (0);
X }
X if (pflag != 0)
X {
X printf("%d\n", head.qh_pid);
X fclose (fpq);
X exit (0);
X }
X if (aflag != 0)
X {
X printf("%d\n", head.qh_noentries);
X fclose (fpq);
X exit (0);
X }
X if (rflag != 0)
X {
X if (head.qh_noentries > 0)
X {
X fread (&entry, sizeof(entry), 1, fpq);
X printf("%d\n", entry.qe_status);
X }
X else printf("%d\n",0);
X fclose (fpq);
X exit (0);
X }
X if (sflag != 0)
X {
X fclose (fpq);
X if (head.qh_proc == 0)
X {
X printf ("Queue has not been run\n");
X exit (0);
X }
X jtimes = (struct tm *)localtime (&head.qh_proc);
X printf ("\n Queue started : %s" ,asctime (jtimes));
X if (head.qh_pid == 0)
X {
X printf("\n Queue is not running\n");
X }
X else
X {
X now = time ((time_t *) 0);
X then = now;
X now -= head.qh_proc;
X now *= 100;
X printf ("\n Available for : %s\n" ,print_time (now, 1));
X }
X if (head.qh_jobcount == 0)
X {
X printf("No jobs run since queue started\n");
X exit(0);
X }
X printf (" No. Jobs Processed: %d\n\n", head.qh_jobcount);
X printf ("Times:\t\t Actual\t\t\tAv. Per Job\n\n");
X printf ("Queued\t\t%16s", print_time(head.qh_queued, 0));
X printf (" %16s\n", print_time(head.qh_queued/head.qh_jobcount, 0));
X printf ("Real\t\t%16s", print_time(head.qh_real, 0));
X printf (" %16s\n", print_time(head.qh_real/head.qh_jobcount, 0));
X printf ("User\t\t%16s", print_time(head.qh_user, 0));
X printf (" %16s\n", print_time(head.qh_user/head.qh_jobcount, 0));
X printf ("System\t\t%16s", print_time(head.qh_system, 0));
X printf (" %16s\n", print_time(head.qh_system/head.qh_jobcount, 0));
X if (head.qh_pid == 0) exit(0);
X head.qh_real *= 10000;
X head.qh_real /= now ;
X printf("\nUtilisation (real/available) %d.%02d%%\n",(head.qh_real/100), (head.qh_real%100));
X if (head.qh_start)
X {
X then -= head.qh_start;
X then *= 100;
X printf ("\nCurrent job not accounted for above, running for : %s\n", print_time(then));
X }
X fclose (fpq);
X exit(0);
X }
X if (qflag != 0)
X {
X if (strcmp (head.qh_defmon, "NONE") == 0)
X {
X fprintf(stderr, "%s has NO default monitor\007\n", queuename);
X fclose (fpq);
X exit(-1);
X }
X puts (head.qh_defmon);
X }
X else
X {
X if ((jflag == 0) && (mflag == 0) && (entryno == 0))
X {
X fprintf(stderr, "No options specified\007\n");
X fclose (fpq);
X exit(0);
X }
X if ((jflag == 0) && (mflag == 0))
X {
X fprintf(stderr, "Entryno specified without j or m\007\n");
X fclose (fpq);
X exit(0);
X }
X if (head.qh_noentries > 0)
X {
X if (entryno == 0) fread (&entry, sizeof(entry), 1, fpq);
X else
X {
X entry.qe_jobno = 0;
X while (entry.qe_jobno != entryno)
X {
X if (fread (&entry, sizeof(entry), 1, fpq) == 0)
X {
X fprintf (stderr, "entry %d does not exist\n", entryno);
X fclose (fpq);
X exit (-1);
X }
X }
X }
X if (jflag != 0)
X {
X strcpy (buff, head.qh_spool);
X if (buff[strlen(buff) -1] != '/') strcat (buff,"/");
X strcat (buff,entry.qe_jcl);
X puts (buff);
X }
X if (mflag != 0)
X {
X if (entry.qe_monitor[0] != 0) puts (entry.qe_monitor);
X else
X {
X if (strcmp (head.qh_defmon, "NONE") == 0)
X {
X fprintf(stderr, "%s has NO default monitor\007\n", queuename);
X fclose (fpq);
X exit(-1);
X }
X puts (head.qh_defmon);
X }
X }
X }
X else
X {
X if (mflag != 0)
X {
X if (strcmp (head.qh_defmon, "NONE") == 0)
X {
X fprintf(stderr, "%s has NO default monitor\007\n", queuename);
X fclose (fpq);
X exit(-1);
X }
X puts (head.qh_defmon);
X }
X else
X {
X fprintf (stderr, "No entries for j or m option\n");
X fclose (fpq);
X exit (-1);
X }
X }
X }
X fclose (fpq);
X exit (0);
X}
END_OF_FILE
if test 8190 -ne `wc -c <'src/qf.c'`; then
echo shar: \"'src/qf.c'\" unpacked with wrong size!
fi
# end of 'src/qf.c'
fi
echo shar: End of archive 5 \(of 6\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 6 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
exit 0 # Just in case...
--
Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD UUCP: uunet!sparky!kent
Phone: (402) 291-8300 FAX: (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.