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