1*48652Sbostic /*- 2*48652Sbostic * Copyright (c) 1985 The Regents of the University of California. 3*48652Sbostic * All rights reserved. 4*48652Sbostic * 5*48652Sbostic * %sccs.include.proprietary.c% 6*48652Sbostic */ 7*48652Sbostic 813634Ssam #ifndef lint 9*48652Sbostic static char sccsid[] = "@(#)anlwrk.c 5.9 (Berkeley) 04/24/91"; 10*48652Sbostic #endif /* not lint */ 1113634Ssam 1213634Ssam #include "uucp.h" 1313634Ssam #include <sys/stat.h> 1417766Sralph #include "uust.h" 1513634Ssam #ifdef NDIR 1613634Ssam #include "ndir.h" 1713634Ssam #else 1813701Ssam #include <sys/dir.h> 1913634Ssam #endif 2018615Sralph #include <ctype.h> 2113634Ssam 2233558Srick #define TLIMIT (15*60L) 2313634Ssam #define NITEMS(X) (sizeof (X) / sizeof ((X)[0])) 2413634Ssam 2517766Sralph int Nfiles = 0; 2617766Sralph char Filent[LLEN][NAMESIZE]; 2718615Sralph extern int TransferSucceeded; 2813634Ssam 2923584Sbloom /*LINTLIBRARY*/ 3023584Sbloom 3118615Sralph /* 3218615Sralph * create a vector of command arguments 3313634Ssam * 3413634Ssam * return codes: 3513634Ssam * 0 - no more work in this file 3613634Ssam * positive number - number of arguments 3713634Ssam */ 3813634Ssam 3913634Ssam /* LOCAL only */ 4013634Ssam int 4113634Ssam anlwrk(file, wvec) 4213634Ssam register char *file, **wvec; 4313634Ssam { 4423584Sbloom static char str[MAXRQST], nstr[MAXRQST], lastfile[MAXFULLNAME] = ""; 4513634Ssam static FILE *fp = NULL; 4618615Sralph static long nextread, nextwrite; 4713634Ssam 4817766Sralph /* 4917766Sralph * If called with a null string, force a shutdown 5013634Ssam * of the current work file. 5113634Ssam */ 5213634Ssam if (file[0] == '\0') { 5313634Ssam if (fp != NULL) 5413634Ssam fclose (fp); 5513634Ssam fp = NULL; 5617766Sralph return 0; 5713634Ssam } 5813634Ssam if (fp == NULL) { 5923584Sbloom if (strncmp(file, lastfile, MAXFULLNAME) == 0) { 6023584Sbloom DEBUG(5,"Workfilename repeated: %s\n", file); 6123584Sbloom return 0; 6223584Sbloom } 6323584Sbloom strncpy(lastfile, file, MAXFULLNAME); 6418615Sralph fp = fopen(subfile(file), "r+w"); 6513634Ssam if (fp == NULL) { 6618615Sralph char *bnp, rqstr[MAXFULLNAME]; 6718615Sralph bnp = rindex(file, '/'); 6818615Sralph sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : file); 6918615Sralph xmv(file, rqstr); 7033943Srick syslog(LOG_WARNING, "fopen(%s) failed: %m", 7133943Srick subfile(file)); 7217766Sralph unlink(subfile(file)); 7317766Sralph return 0; 7413634Ssam } 7517766Sralph Usrf = 0; 7618615Sralph nstr[0] = '\0'; 7718615Sralph nextread = nextwrite = 0L; 7813634Ssam } 7913634Ssam 8018615Sralph if (nstr[0] != '\0' && TransferSucceeded) { 8118615Sralph fseek(fp, nextwrite, 0); 8218615Sralph fputs(nstr, fp); 8318615Sralph fseek(fp, nextread, 0); 8413634Ssam } 8518615Sralph 8618615Sralph do { 8718615Sralph nextwrite = ftell(fp); 8818615Sralph if (fgets(str, MAXRQST, fp) == NULL) { 8918615Sralph fclose(fp); 9018615Sralph if (TransferSucceeded) 9118615Sralph unlink(subfile(file)); 9218615Sralph USRF(USR_COMP); 9318615Sralph US_RRS(file, Usrf); 9418615Sralph Usrf = 0; 9518615Sralph file[0] = '\0'; 9623584Sbloom nstr[0] = '\0'; 9718615Sralph fp = NULL; 9818615Sralph return 0; 9918615Sralph } 10018615Sralph } while (!isupper(str[0])); 10118615Sralph 10218615Sralph nextread = ftell(fp); 10318615Sralph strncpy(nstr, str, MAXRQST); 10418615Sralph nstr[0] = tolower(nstr[0]); 10517766Sralph return getargs(str, wvec, 20); 10613634Ssam } 10713634Ssam 10813634Ssam 10918615Sralph /* 11018615Sralph * build list of work files for given system 11113634Ssam * 11213634Ssam * return value - 1 if work was found, else 0 11313634Ssam * 11413634Ssam */ 11513634Ssam 11613634Ssam /* LOCAL only */ 11713634Ssam int 11813634Ssam bldflst (reqst, dir, pre) 11913634Ssam char *reqst; 12013634Ssam register char *dir, *pre; 12113634Ssam { 12213634Ssam static DIR *dirp = NULL; 12333558Srick register struct direct *dentp; 12433558Srick register int i; 12533558Srick int plen = strlen(pre); 12617766Sralph extern char MaxGrade; 12713634Ssam 12813634Ssam if (dirp == NULL) { 12917766Sralph if ((dirp = opendir(subdir(dir,pre[0]))) == NULL) { 13017766Sralph DEBUG(1,"opendir(%s) FAILS\n",subdir(dir,pre[0])); 13117766Sralph return 0; 13217766Sralph } 13333558Srick } else 13413634Ssam rewinddir(dirp); 13533558Srick 13633558Srick Nfiles = 0; 13733558Srick while ((dentp = readdir(dirp)) != NULL && Nfiles < LLEN) { 13813634Ssam /* Check for two systems with the same prefix. 13913634Ssam * Magic number "5" is 1 for "grade" character plus 14013634Ssam * 4 for sequence number. The point here is to not 14113634Ssam * send work for a system which has as a prefix the 14213634Ssam * name of the system called for. 14313634Ssam * Special case: prefix "X." does not do this check 14413634Ssam * so uuxqt can use bldflst. 14513634Ssam */ 14633558Srick if (!prefix(pre, dentp->d_name) || 14733558Srick (plen != 2 && (dentp->d_namlen-plen) != 5)) { 14833558Srick DEBUG(99,"bldflst rejects %s\n",dentp->d_name); 14913634Ssam continue; 15017766Sralph } 15133558Srick if (dentp->d_name[dentp->d_namlen-5] > MaxGrade) { 15233558Srick DEBUG(8, "bldflst rejects %s, grade too low\n", 15333558Srick dentp->d_name); 15417766Sralph continue; 15517766Sralph } 15613634Ssam if (*reqst == 'c') 15717766Sralph return 1; 15813634Ssam 15933558Srick /* locate position for the new file and make room for it */ 16033558Srick for (i = Nfiles; i > 0; i--) { 16133558Srick if (pcompar(dentp->d_name, Filent[i-1]) <= 0) 16233558Srick break; 16333558Srick if (i <LLEN) 16433558Srick strcpy(Filent[i], Filent[i-1]); 16533558Srick } 16613634Ssam 16733558Srick /* add new file (if there is room), and increase Nfiles if need be */ 16833558Srick if (i < LLEN) { 16933558Srick DEBUG(99,"bldflst accepts %s",dentp->d_name); 17033558Srick DEBUG(99," as Filent[%d]\n", i); 17133558Srick strcpy(Filent[i], dentp->d_name); 17233558Srick if (Nfiles < LLEN) 17333558Srick Nfiles++; 17433558Srick } else 17533558Srick DEBUG(99,"Filent full, %s rejected by bldflst\n", dentp->d_name); 17633558Srick 17713634Ssam 17813634Ssam } 17933558Srick if (Debug >99) 18033558Srick for(i=0;i<Nfiles;i++) 18133558Srick fprintf(stderr,"Filent[%d]=%s\n",i,Filent[i]); 18213634Ssam 18333558Srick return Nfiles > 0; 18413634Ssam } 18513634Ssam 18613634Ssam /* 18713634Ssam Compare priority of filenames p1 and p2. Return: 18813634Ssam * < 0 if p1 "has lower priority than" p2. 18913634Ssam * = 0 if p1 "has priority equal to" p2. 19013634Ssam * > 0 if p1 "has greater priority than" p2. 19113634Ssam * Priority: 19213634Ssam * lower grade wins. 19313634Ssam * lower sequence number wins (unless wrap-around is suspected). 19413634Ssam * 19513634Ssam */ 19613634Ssam /* LOCAL only */ 19713634Ssam pcompar(p1, p2) 19813634Ssam register char *p1, *p2; 19913634Ssam { 20013634Ssam register int rc; 20113634Ssam 20233943Srick /* 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 work vector 22013634Ssam * 22113634Ssam * return codes: 22213634Ssam * positive number - number of arguments 22313634Ssam * 0 - no arguments - fail 22413634Ssam */ 22513634Ssam 22613634Ssam /* EXTERNALLY CALLED */ 22713634Ssam int 22813634Ssam gtwvec(file, dir, wkpre, wrkvec) 22913634Ssam char *dir, *wkpre, **wrkvec; 23013634Ssam register char *file; 23113634Ssam { 23213634Ssam register int nargs, n; 23313634Ssam 23417766Sralph n = 0; 23513634Ssam while ((nargs = anlwrk(file, wrkvec)) == 0) { 23613634Ssam if (++n > 3 || !iswrk(file, "get", dir, wkpre)) 23717766Sralph return 0; 23813634Ssam } 23917766Sralph return nargs; 24013634Ssam } 24113634Ssam 24218615Sralph /* 24313634Ssam * iswrk - this routine will check the work list (list). 24413634Ssam * If it is empty or the present work is exhausted, it 24513634Ssam * will call bldflst to generate a new list. 24613634Ssam * The "reqst" field will be the string "chk" or "get" to 24713634Ssam * check for work, or get the next work file respectively. 24813634Ssam * 24913634Ssam * return codes: 25013634Ssam * 0 - no more work (or some error) 25113634Ssam * 1 - there is work 25213634Ssam * 25313634Ssam */ 25413634Ssam 25513634Ssam /* EXTERNALLY CALLED */ 25613634Ssam int 25713634Ssam iswrk(file, reqst, dir, pre) 25813634Ssam register char *file, *reqst, *dir, *pre; 25913634Ssam { 26013634Ssam static char *lastpre = 0; 26133558Srick register ret = 0; 26233558Srick int i; 26313634Ssam 26413634Ssam /* Starting new system; re-init */ 26533558Srick if (lastpre == 0 || strcmp(lastpre, pre) != SAME) { 26633558Srick /* Force close of work file */ 26733558Srick anlwrk("", (char **)0); 26813634Ssam 26913634Ssam /* Save last worked-on prefix */ 27013634Ssam if (lastpre != 0) 27133558Srick free(lastpre); 27213634Ssam lastpre = malloc((unsigned)(strlen(pre)+1)); 27333558Srick strcpy(lastpre, pre); 27413634Ssam 27533558Srick /* Set the external indexes properly */ 27613634Ssam Nfiles = 0; 27713634Ssam } 27813634Ssam 27933558Srick /* 28033558Srick * If the list is empty or new files have entered 28113634Ssam * the spool area, call "bldflst" to read 28233558Srick * some file names into it. 28313634Ssam */ 28433558Srick if (Nfiles <= 0 || newspool((time_t)TLIMIT)) { 28533558Srick ret = bldflst(reqst, dir, pre); 28633558Srick DEBUG(99, "bldflst returns %d\n", ret); 28733558Srick } 28813634Ssam 28933558Srick /* If they only wanted to check, return 29033558Srick * boolean list not empty. NB: the list 29133558Srick * will be forcibly emptied as soon as 29233558Srick * a new system name is mentioned. 29333558Srick */ 29433558Srick if (*reqst == 'c') 29533558Srick return ret; 29613634Ssam 29733558Srick if (Nfiles-- <= 0) { 29833558Srick /* Didn't find any files in the spool area */ 29933558Srick Nfiles = 0; 30033558Srick return 0; 30113634Ssam } 30233558Srick /* Found some files, return the first one */ 30333558Srick sprintf(file, "%s/%s", dir, Filent[0]); 30433558Srick for (i = 0; i < Nfiles; i++) 30533558Srick strcpy(Filent[i], Filent[i+1]); 30633558Srick return 1; 30713634Ssam } 30813634Ssam 30913634Ssam /* Return non-zero if there is new work in the spool 31013634Ssam * area since last check. Assumes that if the sequence 31113634Ssam * file has been modified, there is new work. This is 31213634Ssam * not absolutely correct, but should be close enough. 31313634Ssam * Only checks every <limit> seconds at most. Called 31413634Ssam * from "iswrk()" when a new work file is requested. 31513634Ssam */ 31613634Ssam /* LOCAL only */ 31713634Ssam int 31813634Ssam newspool(limit) 31913634Ssam time_t limit; 32013634Ssam { 32113634Ssam static time_t lastcheck = 0, lastmod = 0; 32213634Ssam time_t check; 32313634Ssam struct stat mod; 32413634Ssam register int ret = 0; 32513634Ssam 32613634Ssam /* (void) */ time (&check); 32713634Ssam if (check - lastcheck > limit || lastcheck - check > limit) { 32813634Ssam mod.st_mtime = 0; 32913634Ssam /* (void) */ stat (SEQFILE, &mod); 33013634Ssam if (mod.st_mtime != lastmod) 33113634Ssam ret = 1; 33213634Ssam lastmod = mod.st_mtime; 33313634Ssam } 33413634Ssam lastcheck = check; 33517766Sralph return ret; 33613634Ssam } 337