date and time created 85/01/22 13:49:21 by ralph
[unix-history] / usr / src / usr.bin / uucp / libuu / anlwrk.c
CommitLineData
f9e16818 1#ifndef lint
88db71e9 2static char sccsid[] = "@(#)anlwrk.c 5.3 (Berkeley) %G%";
f9e16818
SL
3#endif
4
5#include "uucp.h"
6#include <sys/types.h>
7#include <sys/stat.h>
88db71e9 8#include "uust.h"
f9e16818
SL
9#ifdef NDIR
10#include "ndir.h"
11#else
ed412ce0 12#include <sys/dir.h>
f9e16818
SL
13#endif
14
15/* Re-written to be reasonable
16 * Mon Nov 15 17:19:52 EST 1982
17 * Alan S. Watt (ittvax!swatt)
18 *
19 * Tom Truscott (rti!trt):
20 * Priority ordering cleaned up. New 'pcompar' subroutine.
21 * 'stat' removed (speeds things up).
22 * Possible infinite loop in gtwvec defended against.
23 * Feb 23, 1983
24 *
25 * Changes:
26 *
27 * 1) The check for work is much faster; the first filename
28 * that matches the prefix causes a "yes" return.
29 *
30 * 2) The filename is not "stat" ed , so
31 * there is no massive delay while the list of potential
32 * names is built.
33 *
34 * 3) Requesting work for a new system is now detected so
35 * internal variables are re-initialized properly. In
36 * particular, the stream pointer for the current work
37 * file is properly closed so work for a system which
38 * hangs up will not be sent to the next system called.
39 *
40 * Fri Dec 3 09:31:45 EST 1982
41 *
42 * 5) As new work files are requested, a check is made
43 * every TLIMIT seconds (5 minutes at present) to see
44 * if new files have entered the spool area. Since
45 * work file names are now cached up to LLEN, this can
46 * represent a very long transmission time before new
47 * work enters the list to be processed. If people want
48 * to use the "grade" character to specify a higher
49 * priority, the list must be re-built and re-sorted for
50 * higher priority stuff to have an immediate effect.
51 */
52
53
f9e16818
SL
54#define TLIMIT (5*60L)
55#define NITEMS(X) (sizeof (X) / sizeof ((X)[0]))
56
88db71e9
RC
57int Nfiles = 0;
58char Filent[LLEN][NAMESIZE];
f9e16818
SL
59
60/*******
61 * anlwrk(file, wvec) create a vector of command arguments
62 * char *file, **wvec;
63 *
64 * return codes:
65 * 0 - no more work in this file
66 * positive number - number of arguments
67 */
68
69/* LOCAL only */
70int
71anlwrk(file, wvec)
72register char *file, **wvec;
73{
74 static char str[MAXRQST];
75 static FILE *fp = NULL;
76
88db71e9
RC
77 /*
78 * If called with a null string, force a shutdown
f9e16818 79 * of the current work file.
f9e16818
SL
80 */
81 if (file[0] == '\0') {
82 if (fp != NULL)
83 fclose (fp);
84 fp = NULL;
88db71e9 85 return 0;
f9e16818
SL
86 }
87 if (fp == NULL) {
88 fp = fopen(subfile(file), "r");
89 if (fp == NULL) {
88db71e9
RC
90 unlink(subfile(file));
91 return 0;
f9e16818 92 }
88db71e9 93 Usrf = 0;
f9e16818
SL
94 }
95
96 /* This is what deletes the current work file when EOF
97 * is reached. As this is called from gtwvec, which is
98 * in turn called externally, it is not possible to save
99 * "C." files in case of error, except for line errors,
100 * which shuts down the whole system.
101 */
102 if (fgets(str, MAXRQST, fp) == NULL) {
103 fclose(fp);
104 unlink(subfile(file));
88db71e9
RC
105 USRF(USR_COMP);
106 US_RRS(file, Usrf);
107 Usrf = 0;
f9e16818
SL
108 file[0] = '\0';
109 fp = NULL;
88db71e9 110 return 0;
f9e16818 111 }
88db71e9 112 return getargs(str, wvec, 20);
f9e16818
SL
113}
114
115
116/***
117 * bldflst - build list of work files for given system
118 * Nfiles, Filent are global
119 *
120 * return value - 1 if work was found, else 0
121 *
122 * Jul 26 19:17 1982 (ittvax!swatt). fixed this obnoxious
123 * routine to NOT read all the way through the damned directory
124 * "stat"'ing every file in sight just to get 10 names!!!
125 *
126 * It still reads through the directory from the beginning until
127 * the list is filled, but this is only once every LLEN names.
128 */
129
130/* LOCAL only */
131int
132bldflst (reqst, dir, pre)
133char *reqst;
134register char *dir, *pre;
135{
136 static DIR *dirp = NULL;
137 register nfound;
88db71e9 138 char filename[NAMESIZE];
f9e16818 139 int plen = strlen (pre);
88db71e9
RC
140 int flen;
141 extern char MaxGrade;
f9e16818
SL
142
143 if (dirp == NULL) {
88db71e9
RC
144 if ((dirp = opendir(subdir(dir,pre[0]))) == NULL) {
145 DEBUG(1,"opendir(%s) FAILS\n",subdir(dir,pre[0]));
146 return 0;
147 }
f9e16818
SL
148 }
149 else
150 rewinddir(dirp);
151 for (nfound = 0, Nfiles = 0; gnamef(dirp, filename);) {
152 /* Check for two systems with the same prefix.
153 * Magic number "5" is 1 for "grade" character plus
154 * 4 for sequence number. The point here is to not
155 * send work for a system which has as a prefix the
156 * name of the system called for.
157 * Special case: prefix "X." does not do this check
158 * so uuxqt can use bldflst.
159 */
88db71e9
RC
160 flen = strlen(filename);
161 if (!prefix(pre, filename) || (plen != 2 && flen-plen != 5)) {
162 DEBUG(99,"bldflst rejects %s\n",filename);
f9e16818 163 continue;
88db71e9
RC
164 }
165 if (filename[flen-5] > MaxGrade ) {
166 DEBUG(8,"bldflst rejects %s, grade too low\n",filename);
167 continue;
168 }
f9e16818
SL
169 nfound++;
170 if (*reqst == 'c')
88db71e9 171 return 1;
f9e16818
SL
172 entflst(filename);
173 }
88db71e9 174 return nfound? 1: 0;
f9e16818
SL
175}
176
177/***
178 * entflst - put new name if list is not full
179 * or new name is less than the MAX
180 * now in the list.
181 * Nfiles, Filent[] are modified.
182 * return value - none
183 *
184 */
185
186/* LOCAL only */
187int
188entflst(file)
88db71e9 189register char *file;
f9e16818
SL
190{
191 register int i;
f9e16818 192
88db71e9
RC
193 /* locate position for the new file and make room for it */
194 for (i = Nfiles; i > 0; i--) {
195 if (pcompar(file, Filent[i-1]) >= 0)
196 break;
197 if (i <LLEN)
198 strcpy(Filent[i], Filent[i-1]);
f9e16818
SL
199 }
200
88db71e9
RC
201 /* add new file (if there is room), and increase Nfiles if need be */
202 if (i < LLEN) {
203 strcpy(Filent[i], file);
204 if (Nfiles < LLEN)
205 Nfiles++;
206 }
f9e16818
SL
207}
208
209/*
210 Compare priority of filenames p1 and p2. Return:
211 * < 0 if p1 "has lower priority than" p2.
212 * = 0 if p1 "has priority equal to" p2.
213 * > 0 if p1 "has greater priority than" p2.
214 * Priority:
215 * lower grade wins.
216 * lower sequence number wins (unless wrap-around is suspected).
217 *
218 */
219/* LOCAL only */
220int
221pcompar(p1, p2)
222register char *p1, *p2;
223{
224 register int rc;
225
226 /* assert: strlen(p1) and strlen(p2) are >= 5 */
227 p1 += strlen(p1)-5;
228 p2 += strlen(p2)-5;
229 /* check 'grade' */
230 if (rc = *p2++ - *p1++)
88db71e9 231 return rc;
f9e16818
SL
232 /* check for sequence wrap-around */
233 if (rc = *p2++ - *p1++)
234 if (rc < -10 || rc > 10)
88db71e9 235 return -rc;
f9e16818 236 else
88db71e9 237 return rc;
f9e16818 238 /* check remaining digits */
88db71e9 239 return strcmp(p2, p1);
f9e16818
SL
240}
241
242/***
243 * gtwrkf - get next work file
244 * Nfiles, Filent[] are modified.
245 *
246 * return value:
247 *
248 * 0 - No file gotten
249 * 1 - File successfully gotten.
250 *
251 */
252
253/* LOCAL only */
254gtwrkf(dir, file)
255char *file, *dir;
256{
88db71e9
RC
257 if (Nfiles <= 0)
258 return 0;
259 sprintf(file, "%s/%s", dir, Filent[--Nfiles]);
260 return 1;
f9e16818
SL
261}
262
263/***
88db71e9 264 * gtwvec(file, dir, wkpre, wrkvec) get work vector
f9e16818
SL
265 * char *file, *dir, *wkpre, **wrkvec;
266 *
267 * return codes:
268 * positive number - number of arguments
269 * 0 - no arguments - fail
270 */
271
272/* EXTERNALLY CALLED */
273int
274gtwvec(file, dir, wkpre, wrkvec)
275char *dir, *wkpre, **wrkvec;
276register char *file;
277{
278 register int nargs, n;
279
88db71e9 280 n = 0;
f9e16818
SL
281 while ((nargs = anlwrk(file, wrkvec)) == 0) {
282 if (++n > 3 || !iswrk(file, "get", dir, wkpre))
88db71e9 283 return 0;
f9e16818 284 }
88db71e9 285 return nargs;
f9e16818
SL
286}
287
288/***
289 * iswrk(file, reqst, dir, pre)
290 * char *file, *reqst, *dir, *pre;
291 *
292 * iswrk - this routine will check the work list (list).
293 * If it is empty or the present work is exhausted, it
294 * will call bldflst to generate a new list.
295 * The "reqst" field will be the string "chk" or "get" to
296 * check for work, or get the next work file respectively.
297 *
298 * return codes:
299 * 0 - no more work (or some error)
300 * 1 - there is work
301 *
302 */
303
304/* EXTERNALLY CALLED */
305int
306iswrk(file, reqst, dir, pre)
307register char *file, *reqst, *dir, *pre;
308{
309 static char *lastpre = 0;
310 register ret;
311
312 /* Starting new system; re-init */
313 if (lastpre == 0 || strcmp(lastpre,pre) != 0) {
314 anlwrk ("", (char **)0); /* Force close of work file */
315
316 /* Save last worked-on prefix */
317 if (lastpre != 0)
318 free (lastpre);
319 lastpre = malloc((unsigned)(strlen(pre)+1));
320 strcpy (lastpre, pre);
321
322 /* Set the external indexes properly
323 */
324 Nfiles = 0;
325 }
326
327 /* If the list is empty or new files have entered
328 * the spool area, call "bldflst" to read
329 * some file names into it. Because names can
330 * be put in the list that later turn out to
331 * be unusable (from "gtwrkf"), this operation
332 * continues until either "bldflst" can't find
333 * any new files, or "gtwrkf" signals success.
334 */
335 for (;;) {
336 ret = 0;
88db71e9 337 if (Nfiles == 0 || newspool((time_t)TLIMIT)) {
f9e16818 338 ret = bldflst (reqst, dir, pre);
88db71e9
RC
339 DEBUG(99,"bldflst returns %d\n",ret);
340 }
f9e16818
SL
341
342 /* If they only wanted to check, return
343 * boolean list not empty. NB: the list
344 * will be forcibly emptied as soon as
345 * a new system name is mentioned.
346 */
347 if (*reqst == 'c')
88db71e9 348 return ret;
f9e16818
SL
349
350 if (Nfiles == 0)
88db71e9 351 return 0;
f9e16818
SL
352
353 if (gtwrkf(dir, file))
88db71e9 354 return 1;
f9e16818
SL
355 }
356}
357
358/* Return non-zero if there is new work in the spool
359 * area since last check. Assumes that if the sequence
360 * file has been modified, there is new work. This is
361 * not absolutely correct, but should be close enough.
362 * Only checks every <limit> seconds at most. Called
363 * from "iswrk()" when a new work file is requested.
364 */
365/* LOCAL only */
366int
367newspool(limit)
368time_t limit;
369{
370 static time_t lastcheck = 0, lastmod = 0;
371 time_t check;
372 struct stat mod;
373 register int ret = 0;
374
375 /* (void) */ time (&check);
376 if (check - lastcheck > limit || lastcheck - check > limit) {
377 mod.st_mtime = 0;
378 /* (void) */ stat (SEQFILE, &mod);
379 if (mod.st_mtime != lastmod)
380 ret = 1;
381 lastmod = mod.st_mtime;
382 }
383 lastcheck = check;
88db71e9 384 return ret;
f9e16818 385}