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