|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)anlwrk.c 5.7 (Berkeley) 4/5/88";
3: #endif
4:
5: #include "uucp.h"
6: #include <sys/stat.h>
7: #include "uust.h"
8: #ifdef NDIR
9: #include "ndir.h"
10: #else
11: #include <sys/dir.h>
12: #endif
13: #include <ctype.h>
14:
15: #define TLIMIT (15*60L)
16: #define NITEMS(X) (sizeof (X) / sizeof ((X)[0]))
17:
18: int Nfiles = 0;
19: char Filent[LLEN][NAMESIZE];
20: long fseek(), ftell();
21: extern int TransferSucceeded;
22:
23: /*LINTLIBRARY*/
24:
25: /*
26: * create a vector of command arguments
27: *
28: * return codes:
29: * 0 - no more work in this file
30: * positive number - number of arguments
31: */
32:
33: /* LOCAL only */
34: int
35: anlwrk(file, wvec)
36: register char *file, **wvec;
37: {
38: static char str[MAXRQST], nstr[MAXRQST], lastfile[MAXFULLNAME] = "";
39: static FILE *fp = NULL;
40: static long nextread, nextwrite;
41:
42: /*
43: * If called with a null string, force a shutdown
44: * of the current work file.
45: */
46: if (file[0] == '\0') {
47: if (fp != NULL)
48: fclose (fp);
49: fp = NULL;
50: return 0;
51: }
52: if (fp == NULL) {
53: if (strncmp(file, lastfile, MAXFULLNAME) == 0) {
54: DEBUG(5,"Workfilename repeated: %s\n", file);
55: return 0;
56: }
57: strncpy(lastfile, file, MAXFULLNAME);
58: fp = fopen(subfile(file), "r+w");
59: if (fp == NULL) {
60: char *bnp, rqstr[MAXFULLNAME];
61: bnp = rindex(file, '/');
62: sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : file);
63: xmv(file, rqstr);
64: syslog(LOG_WARNING, "fopen(%s) failed: %m",
65: subfile(file));
66: unlink(subfile(file));
67: return 0;
68: }
69: Usrf = 0;
70: nstr[0] = '\0';
71: nextread = nextwrite = 0L;
72: }
73:
74: if (nstr[0] != '\0' && TransferSucceeded) {
75: fseek(fp, nextwrite, 0);
76: fputs(nstr, fp);
77: fseek(fp, nextread, 0);
78: }
79:
80: do {
81: nextwrite = ftell(fp);
82: if (fgets(str, MAXRQST, fp) == NULL) {
83: fclose(fp);
84: if (TransferSucceeded)
85: unlink(subfile(file));
86: USRF(USR_COMP);
87: US_RRS(file, Usrf);
88: Usrf = 0;
89: file[0] = '\0';
90: nstr[0] = '\0';
91: fp = NULL;
92: return 0;
93: }
94: } while (!isupper(str[0]));
95:
96: nextread = ftell(fp);
97: strncpy(nstr, str, MAXRQST);
98: nstr[0] = tolower(nstr[0]);
99: return getargs(str, wvec, 20);
100: }
101:
102:
103: /*
104: * build list of work files for given system
105: *
106: * return value - 1 if work was found, else 0
107: *
108: */
109:
110: /* LOCAL only */
111: int
112: bldflst (reqst, dir, pre)
113: char *reqst;
114: register char *dir, *pre;
115: {
116: static DIR *dirp = NULL;
117: register struct direct *dentp;
118: register int i;
119: int plen = strlen(pre);
120: extern char MaxGrade;
121:
122: if (dirp == NULL) {
123: if ((dirp = opendir(subdir(dir,pre[0]))) == NULL) {
124: DEBUG(1,"opendir(%s) FAILS\n",subdir(dir,pre[0]));
125: return 0;
126: }
127: } else
128: rewinddir(dirp);
129:
130: Nfiles = 0;
131: while ((dentp = readdir(dirp)) != NULL && Nfiles < LLEN) {
132: /* Check for two systems with the same prefix.
133: * Magic number "5" is 1 for "grade" character plus
134: * 4 for sequence number. The point here is to not
135: * send work for a system which has as a prefix the
136: * name of the system called for.
137: * Special case: prefix "X." does not do this check
138: * so uuxqt can use bldflst.
139: */
140: if (!prefix(pre, dentp->d_name) ||
141: (plen != 2 && (dentp->d_namlen-plen) != 5)) {
142: DEBUG(99,"bldflst rejects %s\n",dentp->d_name);
143: continue;
144: }
145: if (dentp->d_name[dentp->d_namlen-5] > MaxGrade) {
146: DEBUG(8, "bldflst rejects %s, grade too low\n",
147: dentp->d_name);
148: continue;
149: }
150: if (*reqst == 'c')
151: return 1;
152:
153: /* locate position for the new file and make room for it */
154: for (i = Nfiles; i > 0; i--) {
155: if (pcompar(dentp->d_name, Filent[i-1]) <= 0)
156: break;
157: if (i <LLEN)
158: strcpy(Filent[i], Filent[i-1]);
159: }
160:
161: /* add new file (if there is room), and increase Nfiles if need be */
162: if (i < LLEN) {
163: DEBUG(99,"bldflst accepts %s",dentp->d_name);
164: DEBUG(99," as Filent[%d]\n", i);
165: strcpy(Filent[i], dentp->d_name);
166: if (Nfiles < LLEN)
167: Nfiles++;
168: } else
169: DEBUG(99,"Filent full, %s rejected by bldflst\n", dentp->d_name);
170:
171:
172: }
173: if (Debug >99)
174: for(i=0;i<Nfiles;i++)
175: fprintf(stderr,"Filent[%d]=%s\n",i,Filent[i]);
176:
177: return Nfiles > 0;
178: }
179:
180: /*
181: Compare priority of filenames p1 and p2. Return:
182: * < 0 if p1 "has lower priority than" p2.
183: * = 0 if p1 "has priority equal to" p2.
184: * > 0 if p1 "has greater priority than" p2.
185: * Priority:
186: * lower grade wins.
187: * lower sequence number wins (unless wrap-around is suspected).
188: *
189: */
190: /* LOCAL only */
191: pcompar(p1, p2)
192: register char *p1, *p2;
193: {
194: register int rc;
195:
196: /* strlen(p1) and strlen(p2) are >= 5 */
197: p1 += strlen(p1)-5;
198: p2 += strlen(p2)-5;
199: /* check 'grade' */
200: if (rc = *p2++ - *p1++)
201: return rc;
202: /* check for sequence wrap-around */
203: if (rc = *p2++ - *p1++)
204: if (rc < -10 || rc > 10)
205: return -rc;
206: else
207: return rc;
208: /* check remaining digits */
209: return strcmp(p2, p1);
210: }
211:
212: /*
213: * get work vector
214: *
215: * return codes:
216: * positive number - number of arguments
217: * 0 - no arguments - fail
218: */
219:
220: /* EXTERNALLY CALLED */
221: int
222: gtwvec(file, dir, wkpre, wrkvec)
223: char *dir, *wkpre, **wrkvec;
224: register char *file;
225: {
226: register int nargs, n;
227:
228: n = 0;
229: while ((nargs = anlwrk(file, wrkvec)) == 0) {
230: if (++n > 3 || !iswrk(file, "get", dir, wkpre))
231: return 0;
232: }
233: return nargs;
234: }
235:
236: /*
237: * iswrk - this routine will check the work list (list).
238: * If it is empty or the present work is exhausted, it
239: * will call bldflst to generate a new list.
240: * The "reqst" field will be the string "chk" or "get" to
241: * check for work, or get the next work file respectively.
242: *
243: * return codes:
244: * 0 - no more work (or some error)
245: * 1 - there is work
246: *
247: */
248:
249: /* EXTERNALLY CALLED */
250: int
251: iswrk(file, reqst, dir, pre)
252: register char *file, *reqst, *dir, *pre;
253: {
254: static char *lastpre = 0;
255: register ret = 0;
256: int i;
257:
258: /* Starting new system; re-init */
259: if (lastpre == 0 || strcmp(lastpre, pre) != SAME) {
260: /* Force close of work file */
261: anlwrk("", (char **)0);
262:
263: /* Save last worked-on prefix */
264: if (lastpre != 0)
265: free(lastpre);
266: lastpre = malloc((unsigned)(strlen(pre)+1));
267: strcpy(lastpre, pre);
268:
269: /* Set the external indexes properly */
270: Nfiles = 0;
271: }
272:
273: /*
274: * If the list is empty or new files have entered
275: * the spool area, call "bldflst" to read
276: * some file names into it.
277: */
278: if (Nfiles <= 0 || newspool((time_t)TLIMIT)) {
279: ret = bldflst(reqst, dir, pre);
280: DEBUG(99, "bldflst returns %d\n", ret);
281: }
282:
283: /* If they only wanted to check, return
284: * boolean list not empty. NB: the list
285: * will be forcibly emptied as soon as
286: * a new system name is mentioned.
287: */
288: if (*reqst == 'c')
289: return ret;
290:
291: if (Nfiles-- <= 0) {
292: /* Didn't find any files in the spool area */
293: Nfiles = 0;
294: return 0;
295: }
296: /* Found some files, return the first one */
297: sprintf(file, "%s/%s", dir, Filent[0]);
298: for (i = 0; i < Nfiles; i++)
299: strcpy(Filent[i], Filent[i+1]);
300: return 1;
301: }
302:
303: /* Return non-zero if there is new work in the spool
304: * area since last check. Assumes that if the sequence
305: * file has been modified, there is new work. This is
306: * not absolutely correct, but should be close enough.
307: * Only checks every <limit> seconds at most. Called
308: * from "iswrk()" when a new work file is requested.
309: */
310: /* LOCAL only */
311: int
312: newspool(limit)
313: time_t limit;
314: {
315: static time_t lastcheck = 0, lastmod = 0;
316: time_t check;
317: struct stat mod;
318: register int ret = 0;
319:
320: /* (void) */ time (&check);
321: if (check - lastcheck > limit || lastcheck - check > limit) {
322: mod.st_mtime = 0;
323: /* (void) */ stat (SEQFILE, &mod);
324: if (mod.st_mtime != lastmod)
325: ret = 1;
326: lastmod = mod.st_mtime;
327: }
328: lastcheck = check;
329: return ret;
330: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.