xref: /csrg-svn/usr.bin/uucp/libuu/anlwrk.c (revision 18615)
113634Ssam #ifndef lint
2*18615Sralph static char sccsid[] = "@(#)anlwrk.c	5.4 (Berkeley) 04/10/85";
313634Ssam #endif
413634Ssam 
513634Ssam #include "uucp.h"
613634Ssam #include <sys/stat.h>
717766Sralph #include "uust.h"
813634Ssam #ifdef	NDIR
913634Ssam #include "ndir.h"
1013634Ssam #else
1113701Ssam #include <sys/dir.h>
1213634Ssam #endif
13*18615Sralph #include <ctype.h>
1413634Ssam 
1513634Ssam #define TLIMIT	(5*60L)
1613634Ssam #define NITEMS(X)	(sizeof (X) / sizeof ((X)[0]))
1713634Ssam 
1817766Sralph int Nfiles = 0;
1917766Sralph char Filent[LLEN][NAMESIZE];
20*18615Sralph long fseek(), ftell();
21*18615Sralph extern int TransferSucceeded;
2213634Ssam 
23*18615Sralph /*
24*18615Sralph  *	create a vector of command arguments
2513634Ssam  *
2613634Ssam  *	return codes:
2713634Ssam  *		0  -  no more work in this file
2813634Ssam  *		positive number  -  number of arguments
2913634Ssam  */
3013634Ssam 
3113634Ssam /* LOCAL only */
3213634Ssam int
3313634Ssam anlwrk(file, wvec)
3413634Ssam register char *file, **wvec;
3513634Ssam {
36*18615Sralph 	static char str[MAXRQST], nstr[MAXRQST];
3713634Ssam 	static FILE *fp = NULL;
38*18615Sralph 	static long nextread, nextwrite;
3913634Ssam 
4017766Sralph 	/*
4117766Sralph 	 * If called with a null string, force a shutdown
4213634Ssam 	 * of the current work file.
4313634Ssam 	 */
4413634Ssam 	if (file[0] == '\0') {
4513634Ssam 		if (fp != NULL)
4613634Ssam 			fclose (fp);
4713634Ssam 		fp = NULL;
4817766Sralph 		return 0;
4913634Ssam 	}
5013634Ssam 	if (fp == NULL) {
51*18615Sralph 		fp = fopen(subfile(file), "r+w");
5213634Ssam 		if (fp == NULL) {
53*18615Sralph 			char *bnp, rqstr[MAXFULLNAME];
54*18615Sralph 			bnp = rindex(file, '/');
55*18615Sralph 			sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : file);
56*18615Sralph 			xmv(file, rqstr);
57*18615Sralph 			logent(file, "CMD FILE UNREADABLE");
5817766Sralph 			unlink(subfile(file));
5917766Sralph 			return 0;
6013634Ssam 		}
6117766Sralph 		Usrf = 0;
62*18615Sralph 		nstr[0] = '\0';
63*18615Sralph 		nextread = nextwrite = 0L;
6413634Ssam 	}
6513634Ssam 
66*18615Sralph 	if (nstr[0] != '\0' && TransferSucceeded) {
67*18615Sralph 		fseek(fp, nextwrite, 0);
68*18615Sralph 		fputs(nstr, fp);
69*18615Sralph 		fseek(fp, nextread, 0);
7013634Ssam 	}
71*18615Sralph 
72*18615Sralph 	do {
73*18615Sralph 		nextwrite = ftell(fp);
74*18615Sralph 		if (fgets(str, MAXRQST, fp) == NULL) {
75*18615Sralph 			fclose(fp);
76*18615Sralph 			if (TransferSucceeded)
77*18615Sralph 				unlink(subfile(file));
78*18615Sralph 			USRF(USR_COMP);
79*18615Sralph 			US_RRS(file, Usrf);
80*18615Sralph 			Usrf = 0;
81*18615Sralph 			file[0] = '\0';
82*18615Sralph 			fp = NULL;
83*18615Sralph 			return 0;
84*18615Sralph 		}
85*18615Sralph 	} while (!isupper(str[0]));
86*18615Sralph 
87*18615Sralph 	nextread = ftell(fp);
88*18615Sralph 	strncpy(nstr, str, MAXRQST);
89*18615Sralph 	nstr[0] = tolower(nstr[0]);
9017766Sralph 	return getargs(str, wvec, 20);
9113634Ssam }
9213634Ssam 
9313634Ssam 
94*18615Sralph /*
95*18615Sralph  *	build list of work files for given system
9613634Ssam  *
9713634Ssam  *	return value - 1 if work was found, else 0
9813634Ssam  *
9913634Ssam  */
10013634Ssam 
10113634Ssam /* LOCAL only */
10213634Ssam int
10313634Ssam bldflst (reqst, dir, pre)
10413634Ssam char *reqst;
10513634Ssam register char *dir, *pre;
10613634Ssam {
10713634Ssam 	static DIR  *dirp = NULL;
10813634Ssam 	register nfound;
10917766Sralph 	char filename[NAMESIZE];
11013634Ssam 	int plen = strlen (pre);
11117766Sralph 	int flen;
11217766Sralph 	extern char MaxGrade;
11313634Ssam 
11413634Ssam 	if (dirp == NULL) {
11517766Sralph 		if ((dirp = opendir(subdir(dir,pre[0]))) == NULL) {
11617766Sralph 			DEBUG(1,"opendir(%s) FAILS\n",subdir(dir,pre[0]));
11717766Sralph 			return 0;
11817766Sralph 		}
11913634Ssam 	}
12013634Ssam 	else
12113634Ssam 		rewinddir(dirp);
12213634Ssam 	for (nfound = 0, Nfiles = 0; gnamef(dirp, filename);) {
12313634Ssam 		/* Check for two systems with the same prefix.
12413634Ssam 		 * Magic number "5" is 1 for "grade" character plus
12513634Ssam 		 * 4 for sequence number.  The point here is to not
12613634Ssam 		 * send work for a system which has as a prefix the
12713634Ssam 		 * name of the system called for.
12813634Ssam 		 * Special case: prefix "X." does not do this check
12913634Ssam 		 * so uuxqt can use bldflst.
13013634Ssam 		 */
13117766Sralph 		flen = strlen(filename);
13217766Sralph 		if (!prefix(pre, filename) || (plen != 2 && flen-plen != 5)) {
13317766Sralph 			DEBUG(99,"bldflst rejects %s\n",filename);
13413634Ssam 			continue;
13517766Sralph 		}
13617766Sralph 		if (filename[flen-5] > MaxGrade ) {
13717766Sralph 			DEBUG(8,"bldflst rejects %s, grade too low\n",filename);
13817766Sralph 			continue;
13917766Sralph 		}
14013634Ssam 		nfound++;
14113634Ssam 		if (*reqst == 'c')
14217766Sralph 			return 1;
14313634Ssam 		entflst(filename);
14413634Ssam 	}
14517766Sralph 	return  nfound? 1: 0;
14613634Ssam }
14713634Ssam 
148*18615Sralph /*
149*18615Sralph  *	put new name if list is not full  or new name is less than the MAX
15013634Ssam  *		  now in the list.
15113634Ssam  *
15213634Ssam  */
15313634Ssam 
15413634Ssam /* LOCAL only */
15513634Ssam int
15613634Ssam entflst(file)
15717766Sralph register char *file;
15813634Ssam {
15913634Ssam 	register int i;
16013634Ssam 
16117766Sralph 	/* locate position for the new file and make room for it */
16217766Sralph 	for (i = Nfiles; i > 0; i--) {
163*18615Sralph 		if (pcompar(file, Filent[i-1]) <= 0)
16417766Sralph 			break;
16517766Sralph 		if (i <LLEN)
16617766Sralph 			strcpy(Filent[i], Filent[i-1]);
16713634Ssam 	}
16813634Ssam 
16917766Sralph 	/* add new file (if there is room), and increase Nfiles if need be */
17017766Sralph 	if (i < LLEN) {
17117766Sralph 		strcpy(Filent[i], file);
17217766Sralph 		if (Nfiles < LLEN)
17317766Sralph 			Nfiles++;
17417766Sralph 	}
17513634Ssam }
17613634Ssam 
17713634Ssam /*
17813634Ssam   Compare priority of filenames p1 and p2.  Return:
17913634Ssam  *	< 0	if p1 "has lower priority than" p2.
18013634Ssam  *	= 0	if p1 "has priority equal to" p2.
18113634Ssam  *	> 0	if p1 "has greater priority than" p2.
18213634Ssam  * Priority:
18313634Ssam  *	lower grade wins.
18413634Ssam  *	lower sequence number wins (unless wrap-around is suspected).
18513634Ssam  *
18613634Ssam  */
18713634Ssam /* LOCAL only */
18813634Ssam int
18913634Ssam pcompar(p1, p2)
19013634Ssam register char *p1, *p2;
19113634Ssam {
19213634Ssam 	register int rc;
19313634Ssam 
19413634Ssam 	/* assert: strlen(p1) and strlen(p2) are >= 5 */
19513634Ssam 	p1 += strlen(p1)-5;
19613634Ssam 	p2 += strlen(p2)-5;
19713634Ssam 	/* check 'grade' */
19813634Ssam 	if (rc = *p2++ - *p1++)
19917766Sralph 		return rc;
20013634Ssam 	/* check for  sequence wrap-around */
20113634Ssam 	if (rc = *p2++ - *p1++)
20213634Ssam 		if (rc < -10 || rc > 10)
20317766Sralph 			return -rc;
20413634Ssam 		else
20517766Sralph 			return rc;
20613634Ssam 	/* check remaining digits */
20717766Sralph 	return strcmp(p2, p1);
20813634Ssam }
20913634Ssam 
210*18615Sralph /*
211*18615Sralph  *	get next work file
21213634Ssam  *
21313634Ssam  *	return value:
21413634Ssam  *
21513634Ssam  *		0  - No file gotten
21613634Ssam  *		1  - File successfully gotten.
21713634Ssam  *
21813634Ssam  */
21913634Ssam 
22013634Ssam /* LOCAL only */
22113634Ssam gtwrkf(dir, file)
22213634Ssam char *file, *dir;
22313634Ssam {
224*18615Sralph 	register int i;
225*18615Sralph 
226*18615Sralph 	if (Nfiles-- <= 0) {
227*18615Sralph 		Nfiles = 0;
22817766Sralph 		return 0;
229*18615Sralph 	}
230*18615Sralph 	sprintf(file, "%s/%s", dir, Filent[0]);
231*18615Sralph 	for (i=0; i<Nfiles;i++)
232*18615Sralph 		strcpy(Filent[i], Filent[i+1]);
23317766Sralph 	return 1;
23413634Ssam }
23513634Ssam 
236*18615Sralph /*
237*18615Sralph  *	get work vector
23813634Ssam  *
23913634Ssam  *	return codes:
24013634Ssam  *		positive number  -  number of arguments
24113634Ssam  *		0 -  no arguments - fail
24213634Ssam  */
24313634Ssam 
24413634Ssam /* EXTERNALLY CALLED */
24513634Ssam int
24613634Ssam gtwvec(file, dir, wkpre, wrkvec)
24713634Ssam char *dir, *wkpre, **wrkvec;
24813634Ssam register char *file;
24913634Ssam {
25013634Ssam 	register int nargs, n;
25113634Ssam 
25217766Sralph 	n = 0;
25313634Ssam 	while ((nargs = anlwrk(file, wrkvec)) == 0) {
25413634Ssam 		if (++n > 3 || !iswrk(file, "get", dir, wkpre))
25517766Sralph 			return 0;
25613634Ssam 	}
25717766Sralph 	return nargs;
25813634Ssam }
25913634Ssam 
260*18615Sralph /*
26113634Ssam  *	iswrk  -  this routine will check the work list (list).
26213634Ssam  *	If it is empty or the present work is exhausted, it
26313634Ssam  *	will call bldflst to generate a new list.
26413634Ssam  *	The "reqst" field will be the string "chk" or "get" to
26513634Ssam  *	check for work, or get the next work file respectively.
26613634Ssam  *
26713634Ssam  *	return codes:
26813634Ssam  *		0  -  no more work (or some error)
26913634Ssam  *		1  -  there is work
27013634Ssam  *
27113634Ssam  */
27213634Ssam 
27313634Ssam /* EXTERNALLY CALLED */
27413634Ssam int
27513634Ssam iswrk(file, reqst, dir, pre)
27613634Ssam register char *file, *reqst, *dir, *pre;
27713634Ssam {
27813634Ssam 	static char *lastpre = 0;
27913634Ssam 	register ret;
28013634Ssam 
28113634Ssam 	/* Starting new system; re-init */
28213634Ssam 	if (lastpre == 0 || strcmp(lastpre,pre) != 0) {
28313634Ssam 		anlwrk ("", (char **)0);	/* Force close of work file */
28413634Ssam 
28513634Ssam 		/* Save last worked-on prefix */
28613634Ssam 		if (lastpre != 0)
28713634Ssam 			free (lastpre);
28813634Ssam 		lastpre = malloc((unsigned)(strlen(pre)+1));
28913634Ssam 		strcpy (lastpre, pre);
29013634Ssam 
29113634Ssam 		/* Set the external indexes properly
29213634Ssam 		 */
29313634Ssam 		Nfiles = 0;
29413634Ssam 	}
29513634Ssam 
29613634Ssam 	/* If the list is empty or new files have entered
29713634Ssam 	 * the spool area, call "bldflst" to read
29813634Ssam 	 * some file names into it.  Because names can
29913634Ssam 	 * be put in the list that later turn out to
30013634Ssam 	 * be unusable (from "gtwrkf"), this operation
30113634Ssam 	 * continues until either "bldflst" can't find
30213634Ssam 	 * any new files, or "gtwrkf" signals success.
30313634Ssam 	 */
30413634Ssam 	for (;;) {
30513634Ssam 		ret = 0;
306*18615Sralph 		if (Nfiles <= 0 || newspool((time_t)TLIMIT)) {
30713634Ssam 			ret = bldflst (reqst, dir, pre);
30817766Sralph 			DEBUG(99,"bldflst returns %d\n",ret);
30917766Sralph 		}
31013634Ssam 
31113634Ssam 		/* If they only wanted to check, return
31213634Ssam 		 * boolean list not empty.  NB: the list
31313634Ssam 		 * will be forcibly emptied as soon as
31413634Ssam 		 * a new system name is mentioned.
31513634Ssam 		 */
31613634Ssam 		if (*reqst == 'c')
31717766Sralph 			return ret;
31813634Ssam 
319*18615Sralph 		if (Nfiles <= 0)
32017766Sralph 			return 0;
32113634Ssam 
32213634Ssam 		if (gtwrkf(dir, file))
32317766Sralph 			return 1;
32413634Ssam 	}
32513634Ssam }
32613634Ssam 
32713634Ssam /* Return non-zero if there is new work in the spool
32813634Ssam  * area since last check.  Assumes that if the sequence
32913634Ssam  * file has been modified, there is new work. This is
33013634Ssam  * not absolutely correct, but should be close enough.
33113634Ssam  * Only checks every <limit> seconds at most.  Called
33213634Ssam  * from "iswrk()" when a new work file is requested.
33313634Ssam  */
33413634Ssam /* LOCAL only */
33513634Ssam int
33613634Ssam newspool(limit)
33713634Ssam time_t	limit;
33813634Ssam {
33913634Ssam 	static time_t lastcheck = 0, lastmod = 0;
34013634Ssam 	time_t check;
34113634Ssam 	struct stat mod;
34213634Ssam 	register int ret = 0;
34313634Ssam 
34413634Ssam 	/* (void) */ time (&check);
34513634Ssam 	if (check - lastcheck > limit || lastcheck - check > limit) {
34613634Ssam 		mod.st_mtime = 0;
34713634Ssam 		/* (void) */ stat (SEQFILE, &mod);
34813634Ssam 		if (mod.st_mtime != lastmod)
34913634Ssam 			ret = 1;
35013634Ssam 		lastmod = mod.st_mtime;
35113634Ssam 	}
35213634Ssam 	lastcheck = check;
35317766Sralph 	return ret;
35413634Ssam }
355