113634Ssam #ifndef lint 2*23584Sbloom static char sccsid[] = "@(#)anlwrk.c 5.5 (Berkeley) 06/19/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 1318615Sralph #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]; 2018615Sralph long fseek(), ftell(); 2118615Sralph extern int TransferSucceeded; 2213634Ssam 23*23584Sbloom /*LINTLIBRARY*/ 24*23584Sbloom 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 { 38*23584Sbloom 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) { 53*23584Sbloom if (strncmp(file, lastfile, MAXFULLNAME) == 0) { 54*23584Sbloom DEBUG(5,"Workfilename repeated: %s\n", file); 55*23584Sbloom return 0; 56*23584Sbloom } 57*23584Sbloom 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*23584Sbloom logent(subfile(file), "CMD FILE UNREADABLE"); 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'; 89*23584Sbloom 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; 11613634Ssam register nfound; 11717766Sralph char filename[NAMESIZE]; 11813634Ssam int plen = strlen (pre); 11917766Sralph int flen; 12017766Sralph extern char MaxGrade; 12113634Ssam 12213634Ssam if (dirp == NULL) { 12317766Sralph if ((dirp = opendir(subdir(dir,pre[0]))) == NULL) { 12417766Sralph DEBUG(1,"opendir(%s) FAILS\n",subdir(dir,pre[0])); 12517766Sralph return 0; 12617766Sralph } 12713634Ssam } 12813634Ssam else 12913634Ssam rewinddir(dirp); 13013634Ssam for (nfound = 0, Nfiles = 0; gnamef(dirp, filename);) { 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 */ 13917766Sralph flen = strlen(filename); 14017766Sralph if (!prefix(pre, filename) || (plen != 2 && flen-plen != 5)) { 14117766Sralph DEBUG(99,"bldflst rejects %s\n",filename); 14213634Ssam continue; 14317766Sralph } 14417766Sralph if (filename[flen-5] > MaxGrade ) { 14517766Sralph DEBUG(8,"bldflst rejects %s, grade too low\n",filename); 14617766Sralph continue; 14717766Sralph } 14813634Ssam nfound++; 14913634Ssam if (*reqst == 'c') 15017766Sralph return 1; 15113634Ssam entflst(filename); 15213634Ssam } 15317766Sralph return nfound? 1: 0; 15413634Ssam } 15513634Ssam 15618615Sralph /* 15718615Sralph * put new name if list is not full or new name is less than the MAX 15813634Ssam * now in the list. 15913634Ssam * 16013634Ssam */ 16113634Ssam 16213634Ssam /* LOCAL only */ 16313634Ssam int 16413634Ssam entflst(file) 16517766Sralph register char *file; 16613634Ssam { 16713634Ssam register int i; 16813634Ssam 16917766Sralph /* locate position for the new file and make room for it */ 17017766Sralph for (i = Nfiles; i > 0; i--) { 17118615Sralph if (pcompar(file, Filent[i-1]) <= 0) 17217766Sralph break; 17317766Sralph if (i <LLEN) 17417766Sralph strcpy(Filent[i], Filent[i-1]); 17513634Ssam } 17613634Ssam 17717766Sralph /* add new file (if there is room), and increase Nfiles if need be */ 17817766Sralph if (i < LLEN) { 17917766Sralph strcpy(Filent[i], file); 18017766Sralph if (Nfiles < LLEN) 18117766Sralph Nfiles++; 18217766Sralph } 18313634Ssam } 18413634Ssam 18513634Ssam /* 18613634Ssam Compare priority of filenames p1 and p2. Return: 18713634Ssam * < 0 if p1 "has lower priority than" p2. 18813634Ssam * = 0 if p1 "has priority equal to" p2. 18913634Ssam * > 0 if p1 "has greater priority than" p2. 19013634Ssam * Priority: 19113634Ssam * lower grade wins. 19213634Ssam * lower sequence number wins (unless wrap-around is suspected). 19313634Ssam * 19413634Ssam */ 19513634Ssam /* LOCAL only */ 19613634Ssam int 19713634Ssam pcompar(p1, p2) 19813634Ssam register char *p1, *p2; 19913634Ssam { 20013634Ssam register int rc; 20113634Ssam 20213634Ssam /* assert: strlen(p1) and strlen(p2) are >= 5 */ 20313634Ssam p1 += strlen(p1)-5; 20413634Ssam p2 += strlen(p2)-5; 20513634Ssam /* check 'grade' */ 20613634Ssam if (rc = *p2++ - *p1++) 20717766Sralph return rc; 20813634Ssam /* check for sequence wrap-around */ 20913634Ssam if (rc = *p2++ - *p1++) 21013634Ssam if (rc < -10 || rc > 10) 21117766Sralph return -rc; 21213634Ssam else 21317766Sralph return rc; 21413634Ssam /* check remaining digits */ 21517766Sralph return strcmp(p2, p1); 21613634Ssam } 21713634Ssam 21818615Sralph /* 21918615Sralph * get next work file 22013634Ssam * 22113634Ssam * return value: 22213634Ssam * 22313634Ssam * 0 - No file gotten 22413634Ssam * 1 - File successfully gotten. 22513634Ssam * 22613634Ssam */ 22713634Ssam 22813634Ssam /* LOCAL only */ 22913634Ssam gtwrkf(dir, file) 23013634Ssam char *file, *dir; 23113634Ssam { 23218615Sralph register int i; 23318615Sralph 23418615Sralph if (Nfiles-- <= 0) { 23518615Sralph Nfiles = 0; 23617766Sralph return 0; 23718615Sralph } 23818615Sralph sprintf(file, "%s/%s", dir, Filent[0]); 23918615Sralph for (i=0; i<Nfiles;i++) 24018615Sralph strcpy(Filent[i], Filent[i+1]); 24117766Sralph return 1; 24213634Ssam } 24313634Ssam 24418615Sralph /* 24518615Sralph * get work vector 24613634Ssam * 24713634Ssam * return codes: 24813634Ssam * positive number - number of arguments 24913634Ssam * 0 - no arguments - fail 25013634Ssam */ 25113634Ssam 25213634Ssam /* EXTERNALLY CALLED */ 25313634Ssam int 25413634Ssam gtwvec(file, dir, wkpre, wrkvec) 25513634Ssam char *dir, *wkpre, **wrkvec; 25613634Ssam register char *file; 25713634Ssam { 25813634Ssam register int nargs, n; 25913634Ssam 26017766Sralph n = 0; 26113634Ssam while ((nargs = anlwrk(file, wrkvec)) == 0) { 26213634Ssam if (++n > 3 || !iswrk(file, "get", dir, wkpre)) 26317766Sralph return 0; 26413634Ssam } 26517766Sralph return nargs; 26613634Ssam } 26713634Ssam 26818615Sralph /* 26913634Ssam * iswrk - this routine will check the work list (list). 27013634Ssam * If it is empty or the present work is exhausted, it 27113634Ssam * will call bldflst to generate a new list. 27213634Ssam * The "reqst" field will be the string "chk" or "get" to 27313634Ssam * check for work, or get the next work file respectively. 27413634Ssam * 27513634Ssam * return codes: 27613634Ssam * 0 - no more work (or some error) 27713634Ssam * 1 - there is work 27813634Ssam * 27913634Ssam */ 28013634Ssam 28113634Ssam /* EXTERNALLY CALLED */ 28213634Ssam int 28313634Ssam iswrk(file, reqst, dir, pre) 28413634Ssam register char *file, *reqst, *dir, *pre; 28513634Ssam { 28613634Ssam static char *lastpre = 0; 28713634Ssam register ret; 28813634Ssam 28913634Ssam /* Starting new system; re-init */ 29013634Ssam if (lastpre == 0 || strcmp(lastpre,pre) != 0) { 29113634Ssam anlwrk ("", (char **)0); /* Force close of work file */ 29213634Ssam 29313634Ssam /* Save last worked-on prefix */ 29413634Ssam if (lastpre != 0) 29513634Ssam free (lastpre); 29613634Ssam lastpre = malloc((unsigned)(strlen(pre)+1)); 29713634Ssam strcpy (lastpre, pre); 29813634Ssam 29913634Ssam /* Set the external indexes properly 30013634Ssam */ 30113634Ssam Nfiles = 0; 30213634Ssam } 30313634Ssam 30413634Ssam /* If the list is empty or new files have entered 30513634Ssam * the spool area, call "bldflst" to read 30613634Ssam * some file names into it. Because names can 30713634Ssam * be put in the list that later turn out to 30813634Ssam * be unusable (from "gtwrkf"), this operation 30913634Ssam * continues until either "bldflst" can't find 31013634Ssam * any new files, or "gtwrkf" signals success. 31113634Ssam */ 31213634Ssam for (;;) { 31313634Ssam ret = 0; 31418615Sralph if (Nfiles <= 0 || newspool((time_t)TLIMIT)) { 31513634Ssam ret = bldflst (reqst, dir, pre); 31617766Sralph DEBUG(99,"bldflst returns %d\n",ret); 31717766Sralph } 31813634Ssam 31913634Ssam /* If they only wanted to check, return 32013634Ssam * boolean list not empty. NB: the list 32113634Ssam * will be forcibly emptied as soon as 32213634Ssam * a new system name is mentioned. 32313634Ssam */ 32413634Ssam if (*reqst == 'c') 32517766Sralph return ret; 32613634Ssam 32718615Sralph if (Nfiles <= 0) 32817766Sralph return 0; 32913634Ssam 33013634Ssam if (gtwrkf(dir, file)) 33117766Sralph return 1; 33213634Ssam } 33313634Ssam } 33413634Ssam 33513634Ssam /* Return non-zero if there is new work in the spool 33613634Ssam * area since last check. Assumes that if the sequence 33713634Ssam * file has been modified, there is new work. This is 33813634Ssam * not absolutely correct, but should be close enough. 33913634Ssam * Only checks every <limit> seconds at most. Called 34013634Ssam * from "iswrk()" when a new work file is requested. 34113634Ssam */ 34213634Ssam /* LOCAL only */ 34313634Ssam int 34413634Ssam newspool(limit) 34513634Ssam time_t limit; 34613634Ssam { 34713634Ssam static time_t lastcheck = 0, lastmod = 0; 34813634Ssam time_t check; 34913634Ssam struct stat mod; 35013634Ssam register int ret = 0; 35113634Ssam 35213634Ssam /* (void) */ time (&check); 35313634Ssam if (check - lastcheck > limit || lastcheck - check > limit) { 35413634Ssam mod.st_mtime = 0; 35513634Ssam /* (void) */ stat (SEQFILE, &mod); 35613634Ssam if (mod.st_mtime != lastmod) 35713634Ssam ret = 1; 35813634Ssam lastmod = mod.st_mtime; 35913634Ssam } 36013634Ssam lastcheck = check; 36117766Sralph return ret; 36213634Ssam } 363