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