Commit | Line | Data |
---|---|---|
f9e16818 | 1 | #ifndef lint |
88db71e9 | 2 | static 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 |
57 | int Nfiles = 0; |
58 | char 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 */ | |
70 | int | |
71 | anlwrk(file, wvec) | |
72 | register 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 */ | |
131 | int | |
132 | bldflst (reqst, dir, pre) | |
133 | char *reqst; | |
134 | register 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 */ | |
187 | int | |
188 | entflst(file) | |
88db71e9 | 189 | register 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 */ | |
220 | int | |
221 | pcompar(p1, p2) | |
222 | register 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 */ | |
254 | gtwrkf(dir, file) | |
255 | char *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 */ | |
273 | int | |
274 | gtwvec(file, dir, wkpre, wrkvec) | |
275 | char *dir, *wkpre, **wrkvec; | |
276 | register 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 */ | |
305 | int | |
306 | iswrk(file, reqst, dir, pre) | |
307 | register 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 */ | |
366 | int | |
367 | newspool(limit) | |
368 | time_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 | } |