113634Ssam #ifndef lint 2*33943Srick static char sccsid[] = "@(#)anlwrk.c 5.7 (Berkeley) 04/05/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 1533558Srick #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*33943Srick syslog(LOG_WARNING, "fopen(%s) failed: %m", 65*33943Srick subfile(file)); 6617766Sralph unlink(subfile(file)); 6717766Sralph return 0; 6813634Ssam } 6917766Sralph Usrf = 0; 7018615Sralph nstr[0] = '\0'; 7118615Sralph nextread = nextwrite = 0L; 7213634Ssam } 7313634Ssam 7418615Sralph if (nstr[0] != '\0' && TransferSucceeded) { 7518615Sralph fseek(fp, nextwrite, 0); 7618615Sralph fputs(nstr, fp); 7718615Sralph fseek(fp, nextread, 0); 7813634Ssam } 7918615Sralph 8018615Sralph do { 8118615Sralph nextwrite = ftell(fp); 8218615Sralph if (fgets(str, MAXRQST, fp) == NULL) { 8318615Sralph fclose(fp); 8418615Sralph if (TransferSucceeded) 8518615Sralph unlink(subfile(file)); 8618615Sralph USRF(USR_COMP); 8718615Sralph US_RRS(file, Usrf); 8818615Sralph Usrf = 0; 8918615Sralph file[0] = '\0'; 9023584Sbloom nstr[0] = '\0'; 9118615Sralph fp = NULL; 9218615Sralph return 0; 9318615Sralph } 9418615Sralph } while (!isupper(str[0])); 9518615Sralph 9618615Sralph nextread = ftell(fp); 9718615Sralph strncpy(nstr, str, MAXRQST); 9818615Sralph nstr[0] = tolower(nstr[0]); 9917766Sralph return getargs(str, wvec, 20); 10013634Ssam } 10113634Ssam 10213634Ssam 10318615Sralph /* 10418615Sralph * build list of work files for given system 10513634Ssam * 10613634Ssam * return value - 1 if work was found, else 0 10713634Ssam * 10813634Ssam */ 10913634Ssam 11013634Ssam /* LOCAL only */ 11113634Ssam int 11213634Ssam bldflst (reqst, dir, pre) 11313634Ssam char *reqst; 11413634Ssam register char *dir, *pre; 11513634Ssam { 11613634Ssam static DIR *dirp = NULL; 11733558Srick register struct direct *dentp; 11833558Srick register int i; 11933558Srick int plen = strlen(pre); 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 } 12733558Srick } else 12813634Ssam rewinddir(dirp); 12933558Srick 13033558Srick Nfiles = 0; 13133558Srick while ((dentp = readdir(dirp)) != NULL && Nfiles < LLEN) { 13213634Ssam /* Check for two systems with the same prefix. 13313634Ssam * Magic number "5" is 1 for "grade" character plus 13413634Ssam * 4 for sequence number. The point here is to not 13513634Ssam * send work for a system which has as a prefix the 13613634Ssam * name of the system called for. 13713634Ssam * Special case: prefix "X." does not do this check 13813634Ssam * so uuxqt can use bldflst. 13913634Ssam */ 14033558Srick if (!prefix(pre, dentp->d_name) || 14133558Srick (plen != 2 && (dentp->d_namlen-plen) != 5)) { 14233558Srick DEBUG(99,"bldflst rejects %s\n",dentp->d_name); 14313634Ssam continue; 14417766Sralph } 14533558Srick if (dentp->d_name[dentp->d_namlen-5] > MaxGrade) { 14633558Srick DEBUG(8, "bldflst rejects %s, grade too low\n", 14733558Srick dentp->d_name); 14817766Sralph continue; 14917766Sralph } 15013634Ssam if (*reqst == 'c') 15117766Sralph return 1; 15213634Ssam 15333558Srick /* locate position for the new file and make room for it */ 15433558Srick for (i = Nfiles; i > 0; i--) { 15533558Srick if (pcompar(dentp->d_name, Filent[i-1]) <= 0) 15633558Srick break; 15733558Srick if (i <LLEN) 15833558Srick strcpy(Filent[i], Filent[i-1]); 15933558Srick } 16013634Ssam 16133558Srick /* add new file (if there is room), and increase Nfiles if need be */ 16233558Srick if (i < LLEN) { 16333558Srick DEBUG(99,"bldflst accepts %s",dentp->d_name); 16433558Srick DEBUG(99," as Filent[%d]\n", i); 16533558Srick strcpy(Filent[i], dentp->d_name); 16633558Srick if (Nfiles < LLEN) 16733558Srick Nfiles++; 16833558Srick } else 16933558Srick DEBUG(99,"Filent full, %s rejected by bldflst\n", dentp->d_name); 17033558Srick 17113634Ssam 17213634Ssam } 17333558Srick if (Debug >99) 17433558Srick for(i=0;i<Nfiles;i++) 17533558Srick fprintf(stderr,"Filent[%d]=%s\n",i,Filent[i]); 17613634Ssam 17733558Srick return Nfiles > 0; 17813634Ssam } 17913634Ssam 18013634Ssam /* 18113634Ssam Compare priority of filenames p1 and p2. Return: 18213634Ssam * < 0 if p1 "has lower priority than" p2. 18313634Ssam * = 0 if p1 "has priority equal to" p2. 18413634Ssam * > 0 if p1 "has greater priority than" p2. 18513634Ssam * Priority: 18613634Ssam * lower grade wins. 18713634Ssam * lower sequence number wins (unless wrap-around is suspected). 18813634Ssam * 18913634Ssam */ 19013634Ssam /* LOCAL only */ 19113634Ssam pcompar(p1, p2) 19213634Ssam register char *p1, *p2; 19313634Ssam { 19413634Ssam register int rc; 19513634Ssam 196*33943Srick /* 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; 25533558Srick register ret = 0; 25633558Srick int i; 25713634Ssam 25813634Ssam /* Starting new system; re-init */ 25933558Srick if (lastpre == 0 || strcmp(lastpre, pre) != SAME) { 26033558Srick /* Force close of work file */ 26133558Srick anlwrk("", (char **)0); 26213634Ssam 26313634Ssam /* Save last worked-on prefix */ 26413634Ssam if (lastpre != 0) 26533558Srick free(lastpre); 26613634Ssam lastpre = malloc((unsigned)(strlen(pre)+1)); 26733558Srick strcpy(lastpre, pre); 26813634Ssam 26933558Srick /* Set the external indexes properly */ 27013634Ssam Nfiles = 0; 27113634Ssam } 27213634Ssam 27333558Srick /* 27433558Srick * If the list is empty or new files have entered 27513634Ssam * the spool area, call "bldflst" to read 27633558Srick * some file names into it. 27713634Ssam */ 27833558Srick if (Nfiles <= 0 || newspool((time_t)TLIMIT)) { 27933558Srick ret = bldflst(reqst, dir, pre); 28033558Srick DEBUG(99, "bldflst returns %d\n", ret); 28133558Srick } 28213634Ssam 28333558Srick /* If they only wanted to check, return 28433558Srick * boolean list not empty. NB: the list 28533558Srick * will be forcibly emptied as soon as 28633558Srick * a new system name is mentioned. 28733558Srick */ 28833558Srick if (*reqst == 'c') 28933558Srick return ret; 29013634Ssam 29133558Srick if (Nfiles-- <= 0) { 29233558Srick /* Didn't find any files in the spool area */ 29333558Srick Nfiles = 0; 29433558Srick return 0; 29513634Ssam } 29633558Srick /* Found some files, return the first one */ 29733558Srick sprintf(file, "%s/%s", dir, Filent[0]); 29833558Srick for (i = 0; i < Nfiles; i++) 29933558Srick strcpy(Filent[i], Filent[i+1]); 30033558Srick 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