static char sccsid
[] = "@(#)anlwrk.c 5.2 (Berkeley) %G%";
/* Re-written to be reasonable
* Mon Nov 15 17:19:52 EST 1982
* Alan S. Watt (ittvax!swatt)
* Tom Truscott (rti!trt):
* Priority ordering cleaned up. New 'pcompar' subroutine.
* 'stat' removed (speeds things up).
* Possible infinite loop in gtwvec defended against.
* 1) The check for work is much faster; the first filename
* that matches the prefix causes a "yes" return.
* 2) The filename is not "stat" ed , so
* there is no massive delay while the list of potential
* 3) Requesting work for a new system is now detected so
* internal variables are re-initialized properly. In
* particular, the stream pointer for the current work
* file is properly closed so work for a system which
* hangs up will not be sent to the next system called.
* Fri Dec 3 09:31:45 EST 1982
* 5) As new work files are requested, a check is made
* every TLIMIT seconds (5 minutes at present) to see
* if new files have entered the spool area. Since
* work file names are now cached up to LLEN, this can
* represent a very long transmission time before new
* work enters the list to be processed. If people want
* to use the "grade" character to specify a higher
* priority, the list must be re-built and re-sorted for
* higher priority stuff to have an immediate effect.
#define NITEMS(X) (sizeof (X) / sizeof ((X)[0]))
/* These are all used only locally
static char Filent
[LLEN
][NAMESIZE
];
* anlwrk(file, wvec) create a vector of command arguments
* 0 - no more work in this file
* positive number - number of arguments
register char *file
, **wvec
;
static char str
[MAXRQST
];
/* If called with a null string, force a shutdown
* of the current work file.
* John Levine, ima.247, related change in cntl.c
fp
= fopen(subfile(file
), "r");
unlink(subfile(file
)); /* Try to zap the thing. rti!trt */
/* This is what deletes the current work file when EOF
* is reached. As this is called from gtwvec, which is
* in turn called externally, it is not possible to save
* "C." files in case of error, except for line errors,
* which shuts down the whole system.
if (fgets(str
, MAXRQST
, fp
) == NULL
) {
return(getargs(str
, wvec
));
* bldflst - build list of work files for given system
* Nfiles, Filent are global
* return value - 1 if work was found, else 0
* Jul 26 19:17 1982 (ittvax!swatt). fixed this obnoxious
* routine to NOT read all the way through the damned directory
* "stat"'ing every file in sight just to get 10 names!!!
* It still reads through the directory from the beginning until
* the list is filled, but this is only once every LLEN names.
bldflst (reqst
, dir
, pre
)
register char *dir
, *pre
;
char filename
[NAMESIZE
]; /* @@@ NB: this needs new dir stuff */
if ((dirp
= opendir(subdir(dir
,pre
[0]), "r")) == NULL
)
for (nfound
= 0, Nfiles
= 0; gnamef(dirp
, filename
);) {
/* Check for two systems with the same prefix.
* Magic number "5" is 1 for "grade" character plus
* 4 for sequence number. The point here is to not
* send work for a system which has as a prefix the
* name of the system called for.
* Special case: prefix "X." does not do this check
* so uuxqt can use bldflst.
if (!prefix(pre
, filename
)
|| (plen
!= 2 && strlen(filename
)-plen
!= 5))
* entflst - put new name if list is not full
* or new name is less than the MAX
* Nfiles, Filent[] are modified.
/* If there is room in the table, just add it. */
strcpy(Filent
[Nfiles
++], file
);
/* Find lowest priority file in table */
for (i
= 1; i
< Nfiles
; i
++)
if (pcompar(Filent
[i
], p
) < 0)
* If new candidate is of higher priority
* that the lowest priority file in the table,
* replace the table entry.
if (pcompar(p
, file
) < 0)
Compare priority of filenames p1 and p2. Return:
* < 0 if p1 "has lower priority than" p2.
* = 0 if p1 "has priority equal to" p2.
* > 0 if p1 "has greater priority than" p2.
* lower sequence number wins (unless wrap-around is suspected).
/* assert: strlen(p1) and strlen(p2) are >= 5 */
/* check for sequence wrap-around */
/* check remaining digits */
* gtwrkf - get next work file
* Nfiles, Filent[] are modified.
* 1 - File successfully gotten.
/* Find highest priority file in table */
for (i
= 1; i
< Nfiles
; i
++)
if (pcompar(Filent
[i
], p
) > 0)
sprintf(file
, "%s/%s", dir
, p
);
strcpy(p
, Filent
[--Nfiles
]);
* gtwvec(file, dir, wkpre, wrkvec) get work vector
* char *file, *dir, *wkpre, **wrkvec;
* positive number - number of arguments
* 0 - no arguments - fail
gtwvec(file
, dir
, wkpre
, wrkvec
)
char *dir
, *wkpre
, **wrkvec
;
n
= 0; /* Break possible infinite loop. rti!trt */
while ((nargs
= anlwrk(file
, wrkvec
)) == 0) {
if (++n
> 3 || !iswrk(file
, "get", dir
, wkpre
))
* iswrk(file, reqst, dir, pre)
* char *file, *reqst, *dir, *pre;
* iswrk - this routine will check the work list (list).
* If it is empty or the present work is exhausted, it
* will call bldflst to generate a new list.
* The "reqst" field will be the string "chk" or "get" to
* check for work, or get the next work file respectively.
* 0 - no more work (or some error)
iswrk(file
, reqst
, dir
, pre
)
register char *file
, *reqst
, *dir
, *pre
;
static char *lastpre
= 0;
/* Starting new system; re-init */
if (lastpre
== 0 || strcmp(lastpre
,pre
) != 0) {
anlwrk ("", (char **)0); /* Force close of work file */
/* Save last worked-on prefix */
lastpre
= malloc((unsigned)(strlen(pre
)+1));
/* Set the external indexes properly
/* If the list is empty or new files have entered
* the spool area, call "bldflst" to read
* some file names into it. Because names can
* be put in the list that later turn out to
* be unusable (from "gtwrkf"), this operation
* continues until either "bldflst" can't find
* any new files, or "gtwrkf" signals success.
if (Nfiles
== 0 || newspool((time_t)TLIMIT
))
ret
= bldflst (reqst
, dir
, pre
);
/* If they only wanted to check, return
* boolean list not empty. NB: the list
* will be forcibly emptied as soon as
* a new system name is mentioned.
/* Return non-zero if there is new work in the spool
* area since last check. Assumes that if the sequence
* file has been modified, there is new work. This is
* not absolutely correct, but should be close enough.
* Only checks every <limit> seconds at most. Called
* from "iswrk()" when a new work file is requested.
static time_t lastcheck
= 0, lastmod
= 0;
/* (void) */ time (&check
);
if (check
- lastcheck
> limit
|| lastcheck
- check
> limit
) {
/* (void) */ stat (SEQFILE
, &mod
);
if (mod
.st_mtime
!= lastmod
)