xref: /csrg-svn/usr.bin/uucp/libuu/anlwrk.c (revision 33558)
113634Ssam #ifndef lint
2*33558Srick static char sccsid[] = "@(#)anlwrk.c	5.6 (Berkeley) 02/24/88";
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
1318615Sralph #include <ctype.h>
1413634Ssam 
15*33558Srick #define TLIMIT	(15*60L)
1613634Ssam #define NITEMS(X)	(sizeof (X) / sizeof ((X)[0]))
1713634Ssam 
1817766Sralph int Nfiles = 0;
1917766Sralph char Filent[LLEN][NAMESIZE];
2018615Sralph long fseek(), ftell();
2118615Sralph extern int TransferSucceeded;
2213634Ssam 
2323584Sbloom /*LINTLIBRARY*/
2423584Sbloom 
2518615Sralph /*
2618615Sralph  *	create a vector of command arguments
2713634Ssam  *
2813634Ssam  *	return codes:
2913634Ssam  *		0  -  no more work in this file
3013634Ssam  *		positive number  -  number of arguments
3113634Ssam  */
3213634Ssam 
3313634Ssam /* LOCAL only */
3413634Ssam int
3513634Ssam anlwrk(file, wvec)
3613634Ssam register char *file, **wvec;
3713634Ssam {
3823584Sbloom 	static char str[MAXRQST], nstr[MAXRQST], lastfile[MAXFULLNAME] = "";
3913634Ssam 	static FILE *fp = NULL;
4018615Sralph 	static long nextread, nextwrite;
4113634Ssam 
4217766Sralph 	/*
4317766Sralph 	 * If called with a null string, force a shutdown
4413634Ssam 	 * of the current work file.
4513634Ssam 	 */
4613634Ssam 	if (file[0] == '\0') {
4713634Ssam 		if (fp != NULL)
4813634Ssam 			fclose (fp);
4913634Ssam 		fp = NULL;
5017766Sralph 		return 0;
5113634Ssam 	}
5213634Ssam 	if (fp == NULL) {
5323584Sbloom 		if (strncmp(file, lastfile, MAXFULLNAME) == 0) {
5423584Sbloom 			DEBUG(5,"Workfilename repeated: %s\n", file);
5523584Sbloom 			return 0;
5623584Sbloom 		}
5723584Sbloom 		strncpy(lastfile, file, MAXFULLNAME);
5818615Sralph 		fp = fopen(subfile(file), "r+w");
5913634Ssam 		if (fp == NULL) {
6018615Sralph 			char *bnp, rqstr[MAXFULLNAME];
6118615Sralph 			bnp = rindex(file, '/');
6218615Sralph 			sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : file);
6318615Sralph 			xmv(file, rqstr);
64*33558Srick 			assert("CMD FILE UNREADABLE", subfile(file), 0);
6517766Sralph 			unlink(subfile(file));
6617766Sralph 			return 0;
6713634Ssam 		}
6817766Sralph 		Usrf = 0;
6918615Sralph 		nstr[0] = '\0';
7018615Sralph 		nextread = nextwrite = 0L;
7113634Ssam 	}
7213634Ssam 
7318615Sralph 	if (nstr[0] != '\0' && TransferSucceeded) {
7418615Sralph 		fseek(fp, nextwrite, 0);
7518615Sralph 		fputs(nstr, fp);
7618615Sralph 		fseek(fp, nextread, 0);
7713634Ssam 	}
7818615Sralph 
7918615Sralph 	do {
8018615Sralph 		nextwrite = ftell(fp);
8118615Sralph 		if (fgets(str, MAXRQST, fp) == NULL) {
8218615Sralph 			fclose(fp);
8318615Sralph 			if (TransferSucceeded)
8418615Sralph 				unlink(subfile(file));
8518615Sralph 			USRF(USR_COMP);
8618615Sralph 			US_RRS(file, Usrf);
8718615Sralph 			Usrf = 0;
8818615Sralph 			file[0] = '\0';
8923584Sbloom 			nstr[0] = '\0';
9018615Sralph 			fp = NULL;
9118615Sralph 			return 0;
9218615Sralph 		}
9318615Sralph 	} while (!isupper(str[0]));
9418615Sralph 
9518615Sralph 	nextread = ftell(fp);
9618615Sralph 	strncpy(nstr, str, MAXRQST);
9718615Sralph 	nstr[0] = tolower(nstr[0]);
9817766Sralph 	return getargs(str, wvec, 20);
9913634Ssam }
10013634Ssam 
10113634Ssam 
10218615Sralph /*
10318615Sralph  *	build list of work files for given system
10413634Ssam  *
10513634Ssam  *	return value - 1 if work was found, else 0
10613634Ssam  *
10713634Ssam  */
10813634Ssam 
10913634Ssam /* LOCAL only */
11013634Ssam int
11113634Ssam bldflst (reqst, dir, pre)
11213634Ssam char *reqst;
11313634Ssam register char *dir, *pre;
11413634Ssam {
11513634Ssam 	static DIR  *dirp = NULL;
116*33558Srick 	register struct direct *dentp;
117*33558Srick 	register int i;
118*33558Srick 	int plen = strlen(pre);
11917766Sralph 	extern char MaxGrade;
12013634Ssam 
12113634Ssam 	if (dirp == NULL) {
12217766Sralph 		if ((dirp = opendir(subdir(dir,pre[0]))) == NULL) {
12317766Sralph 			DEBUG(1,"opendir(%s) FAILS\n",subdir(dir,pre[0]));
12417766Sralph 			return 0;
12517766Sralph 		}
126*33558Srick 	} else
12713634Ssam 		rewinddir(dirp);
128*33558Srick 
129*33558Srick 	Nfiles = 0;
130*33558Srick 	while ((dentp = readdir(dirp)) != NULL && Nfiles < LLEN) {
13113634Ssam 		/* Check for two systems with the same prefix.
13213634Ssam 		 * Magic number "5" is 1 for "grade" character plus
13313634Ssam 		 * 4 for sequence number.  The point here is to not
13413634Ssam 		 * send work for a system which has as a prefix the
13513634Ssam 		 * name of the system called for.
13613634Ssam 		 * Special case: prefix "X." does not do this check
13713634Ssam 		 * so uuxqt can use bldflst.
13813634Ssam 		 */
139*33558Srick 		if (!prefix(pre, dentp->d_name) ||
140*33558Srick 			(plen != 2 && (dentp->d_namlen-plen) != 5)) {
141*33558Srick 			DEBUG(99,"bldflst rejects %s\n",dentp->d_name);
14213634Ssam 			continue;
14317766Sralph 		}
144*33558Srick 		if (dentp->d_name[dentp->d_namlen-5] > MaxGrade) {
145*33558Srick 			DEBUG(8, "bldflst rejects %s, grade too low\n",
146*33558Srick 				dentp->d_name);
14717766Sralph 			continue;
14817766Sralph 		}
14913634Ssam 		if (*reqst == 'c')
15017766Sralph 			return 1;
15113634Ssam 
152*33558Srick 		/* locate position for the new file and make room for it */
153*33558Srick 		for (i = Nfiles; i > 0; i--) {
154*33558Srick 			if (pcompar(dentp->d_name, Filent[i-1]) <= 0)
155*33558Srick 				break;
156*33558Srick 			if (i <LLEN)
157*33558Srick 				strcpy(Filent[i], Filent[i-1]);
158*33558Srick 		}
15913634Ssam 
160*33558Srick 		/* add new file (if there is room), and increase Nfiles if need be */
161*33558Srick 		if (i < LLEN) {
162*33558Srick 			DEBUG(99,"bldflst accepts %s",dentp->d_name);
163*33558Srick 			DEBUG(99," as Filent[%d]\n", i);
164*33558Srick 			strcpy(Filent[i], dentp->d_name);
165*33558Srick 			if (Nfiles < LLEN)
166*33558Srick 				Nfiles++;
167*33558Srick 		} else
168*33558Srick 			DEBUG(99,"Filent full, %s rejected by bldflst\n", dentp->d_name);
169*33558Srick 
17013634Ssam 
17113634Ssam 	}
172*33558Srick 	if (Debug >99)
173*33558Srick 		for(i=0;i<Nfiles;i++)
174*33558Srick 			fprintf(stderr,"Filent[%d]=%s\n",i,Filent[i]);
17513634Ssam 
176*33558Srick 	return Nfiles > 0;
17713634Ssam }
17813634Ssam 
17913634Ssam /*
18013634Ssam   Compare priority of filenames p1 and p2.  Return:
18113634Ssam  *	< 0	if p1 "has lower priority than" p2.
18213634Ssam  *	= 0	if p1 "has priority equal to" p2.
18313634Ssam  *	> 0	if p1 "has greater priority than" p2.
18413634Ssam  * Priority:
18513634Ssam  *	lower grade wins.
18613634Ssam  *	lower sequence number wins (unless wrap-around is suspected).
18713634Ssam  *
18813634Ssam  */
18913634Ssam /* LOCAL only */
19013634Ssam int
19113634Ssam pcompar(p1, p2)
19213634Ssam register char *p1, *p2;
19313634Ssam {
19413634Ssam 	register int rc;
19513634Ssam 
19613634Ssam 	/* assert: strlen(p1) and strlen(p2) are >= 5 */
19713634Ssam 	p1 += strlen(p1)-5;
19813634Ssam 	p2 += strlen(p2)-5;
19913634Ssam 	/* check 'grade' */
20013634Ssam 	if (rc = *p2++ - *p1++)
20117766Sralph 		return rc;
20213634Ssam 	/* check for  sequence wrap-around */
20313634Ssam 	if (rc = *p2++ - *p1++)
20413634Ssam 		if (rc < -10 || rc > 10)
20517766Sralph 			return -rc;
20613634Ssam 		else
20717766Sralph 			return rc;
20813634Ssam 	/* check remaining digits */
20917766Sralph 	return strcmp(p2, p1);
21013634Ssam }
21113634Ssam 
21218615Sralph /*
21318615Sralph  *	get work vector
21413634Ssam  *
21513634Ssam  *	return codes:
21613634Ssam  *		positive number  -  number of arguments
21713634Ssam  *		0 -  no arguments - fail
21813634Ssam  */
21913634Ssam 
22013634Ssam /* EXTERNALLY CALLED */
22113634Ssam int
22213634Ssam gtwvec(file, dir, wkpre, wrkvec)
22313634Ssam char *dir, *wkpre, **wrkvec;
22413634Ssam register char *file;
22513634Ssam {
22613634Ssam 	register int nargs, n;
22713634Ssam 
22817766Sralph 	n = 0;
22913634Ssam 	while ((nargs = anlwrk(file, wrkvec)) == 0) {
23013634Ssam 		if (++n > 3 || !iswrk(file, "get", dir, wkpre))
23117766Sralph 			return 0;
23213634Ssam 	}
23317766Sralph 	return nargs;
23413634Ssam }
23513634Ssam 
23618615Sralph /*
23713634Ssam  *	iswrk  -  this routine will check the work list (list).
23813634Ssam  *	If it is empty or the present work is exhausted, it
23913634Ssam  *	will call bldflst to generate a new list.
24013634Ssam  *	The "reqst" field will be the string "chk" or "get" to
24113634Ssam  *	check for work, or get the next work file respectively.
24213634Ssam  *
24313634Ssam  *	return codes:
24413634Ssam  *		0  -  no more work (or some error)
24513634Ssam  *		1  -  there is work
24613634Ssam  *
24713634Ssam  */
24813634Ssam 
24913634Ssam /* EXTERNALLY CALLED */
25013634Ssam int
25113634Ssam iswrk(file, reqst, dir, pre)
25213634Ssam register char *file, *reqst, *dir, *pre;
25313634Ssam {
25413634Ssam 	static char *lastpre = 0;
255*33558Srick 	register ret = 0;
256*33558Srick 	int i;
25713634Ssam 
25813634Ssam 	/* Starting new system; re-init */
259*33558Srick 	if (lastpre == 0 || strcmp(lastpre, pre) != SAME) {
260*33558Srick 		/* Force close of work file */
261*33558Srick 		anlwrk("", (char **)0);
26213634Ssam 
26313634Ssam 		/* Save last worked-on prefix */
26413634Ssam 		if (lastpre != 0)
265*33558Srick 			free(lastpre);
26613634Ssam 		lastpre = malloc((unsigned)(strlen(pre)+1));
267*33558Srick 		strcpy(lastpre, pre);
26813634Ssam 
269*33558Srick 		/* Set the external indexes properly */
27013634Ssam 		Nfiles = 0;
27113634Ssam 	}
27213634Ssam 
273*33558Srick 	/*
274*33558Srick 	 * If the list is empty or new files have entered
27513634Ssam 	 * the spool area, call "bldflst" to read
276*33558Srick 	 * some file names into it.
27713634Ssam 	 */
278*33558Srick 	if (Nfiles <= 0 || newspool((time_t)TLIMIT)) {
279*33558Srick 		ret = bldflst(reqst, dir, pre);
280*33558Srick 		DEBUG(99, "bldflst returns %d\n", ret);
281*33558Srick 	}
28213634Ssam 
283*33558Srick 	/* If they only wanted to check, return
284*33558Srick 	 * boolean list not empty.  NB: the list
285*33558Srick 	 * will be forcibly emptied as soon as
286*33558Srick 	 * a new system name is mentioned.
287*33558Srick 	 */
288*33558Srick 	if (*reqst == 'c')
289*33558Srick 		return ret;
29013634Ssam 
291*33558Srick 	if (Nfiles-- <= 0) {
292*33558Srick 		/* Didn't find any files in the spool area */
293*33558Srick 		Nfiles = 0;
294*33558Srick 		return 0;
29513634Ssam 	}
296*33558Srick 	/* Found some files, return the first one */
297*33558Srick 	sprintf(file, "%s/%s", dir, Filent[0]);
298*33558Srick 	for (i = 0; i < Nfiles; i++)
299*33558Srick 		strcpy(Filent[i], Filent[i+1]);
300*33558Srick 	return 1;
30113634Ssam }
30213634Ssam 
30313634Ssam /* Return non-zero if there is new work in the spool
30413634Ssam  * area since last check.  Assumes that if the sequence
30513634Ssam  * file has been modified, there is new work. This is
30613634Ssam  * not absolutely correct, but should be close enough.
30713634Ssam  * Only checks every <limit> seconds at most.  Called
30813634Ssam  * from "iswrk()" when a new work file is requested.
30913634Ssam  */
31013634Ssam /* LOCAL only */
31113634Ssam int
31213634Ssam newspool(limit)
31313634Ssam time_t	limit;
31413634Ssam {
31513634Ssam 	static time_t lastcheck = 0, lastmod = 0;
31613634Ssam 	time_t check;
31713634Ssam 	struct stat mod;
31813634Ssam 	register int ret = 0;
31913634Ssam 
32013634Ssam 	/* (void) */ time (&check);
32113634Ssam 	if (check - lastcheck > limit || lastcheck - check > limit) {
32213634Ssam 		mod.st_mtime = 0;
32313634Ssam 		/* (void) */ stat (SEQFILE, &mod);
32413634Ssam 		if (mod.st_mtime != lastmod)
32513634Ssam 			ret = 1;
32613634Ssam 		lastmod = mod.st_mtime;
32713634Ssam 	}
32813634Ssam 	lastcheck = check;
32917766Sralph 	return ret;
33013634Ssam }
331