BSD 4_4 release
[unix-history] / usr / src / usr.bin / uucp / libuu / anlwrk.c
index 53d6dd2..7d37b63 100644 (file)
@@ -1,9 +1,17 @@
+/*-
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This module is believed to contain source code proprietary to AT&T.
+ * Use and redistribution is subject to the Berkeley Software License
+ * Agreement and your Software Agreement with AT&T (Western Electric).
+ */
+
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)anlwrk.c   5.3 (Berkeley) %G%";
-#endif
+static char sccsid[] = "@(#)anlwrk.c   8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
 
 #include "uucp.h"
 
 #include "uucp.h"
-#include <sys/types.h>
 #include <sys/stat.h>
 #include "uust.h"
 #ifdef NDIR
 #include <sys/stat.h>
 #include "uust.h"
 #ifdef NDIR
@@ -11,55 +19,19 @@ static char sccsid[] = "@(#)anlwrk.c        5.3 (Berkeley) %G%";
 #else
 #include <sys/dir.h>
 #endif
 #else
 #include <sys/dir.h>
 #endif
+#include <ctype.h>
 
 
-/* Re-written to be reasonable
- * Mon Nov 15 17:19:52 EST 1982
- * Alan S. Watt (ittvax!swatt)
- *
- * Tom Truscott (rti!trt):
- * Priority ordering cleaned up.  New 'pcompar' subroutine.
- * 'stat' removed (speeds things up).
- * Possible infinite loop in gtwvec defended against.
- * Feb 23, 1983
- *
- * Changes:
- *
- *  1) The check for work is much faster; the first filename
- *     that matches the prefix causes a "yes" return.
- *
- *  2) The filename is not "stat" ed , so
- *     there is no massive delay while the list of potential
- *     names is built.
- *
- *  3) Requesting work for a new system is now detected so
- *     internal variables are re-initialized properly.  In
- *     particular, the stream pointer for the current work
- *     file is properly closed so work for a system which
- *     hangs up will not be sent to the next system called.
- *
- * Fri Dec  3 09:31:45 EST 1982
- *
- *  5) As new work files are requested, a check is made
- *     every TLIMIT seconds (5 minutes at present) to see
- *     if new files have entered the spool area.  Since
- *     work file names are now cached up to LLEN, this can
- *     represent a very long transmission time before new
- *     work enters the list to be processed.  If people want
- *     to use the "grade" character to specify a higher
- *     priority, the list must be re-built and re-sorted for
- *     higher priority stuff to have an immediate effect.
- */
-
-
-#define TLIMIT (5*60L)
+#define TLIMIT (15*60L)
 #define NITEMS(X)      (sizeof (X) / sizeof ((X)[0]))
 
 int Nfiles = 0;
 char Filent[LLEN][NAMESIZE];
 #define NITEMS(X)      (sizeof (X) / sizeof ((X)[0]))
 
 int Nfiles = 0;
 char Filent[LLEN][NAMESIZE];
+extern int TransferSucceeded;
 
 
-/*******
- *     anlwrk(file, wvec)      create a vector of command arguments
- *     char *file, **wvec;
+/*LINTLIBRARY*/
+
+/*
+ *     create a vector of command arguments
  *
  *     return codes:
  *             0  -  no more work in this file
  *
  *     return codes:
  *             0  -  no more work in this file
@@ -71,8 +43,9 @@ int
 anlwrk(file, wvec)
 register char *file, **wvec;
 {
 anlwrk(file, wvec)
 register char *file, **wvec;
 {
-       static char str[MAXRQST];
+       static char str[MAXRQST], nstr[MAXRQST], lastfile[MAXFULLNAME] = "";
        static FILE *fp = NULL;
        static FILE *fp = NULL;
+       static long nextread, nextwrite;
 
        /*
         * If called with a null string, force a shutdown
 
        /*
         * If called with a null string, force a shutdown
@@ -85,46 +58,61 @@ register char *file, **wvec;
                return 0;
        }
        if (fp == NULL) {
                return 0;
        }
        if (fp == NULL) {
-               fp = fopen(subfile(file), "r");
+               if (strncmp(file, lastfile, MAXFULLNAME) == 0) { 
+                       DEBUG(5,"Workfilename repeated: %s\n", file);
+                       return 0;
+               }
+               strncpy(lastfile, file, MAXFULLNAME);
+               fp = fopen(subfile(file), "r+w");
                if (fp == NULL) {
                if (fp == NULL) {
+                       char *bnp, rqstr[MAXFULLNAME];
+                       bnp = rindex(file, '/');
+                       sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : file);
+                       xmv(file, rqstr);
+                       syslog(LOG_WARNING, "fopen(%s) failed: %m",
+                               subfile(file));
                        unlink(subfile(file));
                        return 0;
                }
                Usrf = 0;
                        unlink(subfile(file));
                        return 0;
                }
                Usrf = 0;
+               nstr[0] = '\0';
+               nextread = nextwrite = 0L;
        }
 
        }
 
-       /* This is what deletes the current work file when EOF
-        * is reached.  As this is called from gtwvec, which is
-        * in turn called externally, it is not possible to save
-        * "C." files in case of error, except for line errors,
-        * which shuts down the whole system.
-        */
-       if (fgets(str, MAXRQST, fp) == NULL) {
-               fclose(fp);
-               unlink(subfile(file));
-               USRF(USR_COMP);
-               US_RRS(file, Usrf);
-               Usrf = 0;
-               file[0] = '\0';
-               fp = NULL;
-               return 0;
+       if (nstr[0] != '\0' && TransferSucceeded) {
+               fseek(fp, nextwrite, 0);
+               fputs(nstr, fp);
+               fseek(fp, nextread, 0);
        }
        }
+
+       do {
+               nextwrite = ftell(fp);
+               if (fgets(str, MAXRQST, fp) == NULL) {
+                       fclose(fp);
+                       if (TransferSucceeded)
+                               unlink(subfile(file));
+                       USRF(USR_COMP);
+                       US_RRS(file, Usrf);
+                       Usrf = 0;
+                       file[0] = '\0';
+                       nstr[0] = '\0';
+                       fp = NULL;
+                       return 0;
+               }
+       } while (!isupper(str[0]));
+
+       nextread = ftell(fp);
+       strncpy(nstr, str, MAXRQST);
+       nstr[0] = tolower(nstr[0]);
        return getargs(str, wvec, 20);
 }
 
 
        return getargs(str, wvec, 20);
 }
 
 
-/***
- *     bldflst - build list of work files for given system
- *      Nfiles, Filent are global
+/*
+ *     build list of work files for given system
  *
  *     return value - 1 if work was found, else 0
  *
  *
  *     return value - 1 if work was found, else 0
  *
- * Jul 26 19:17 1982 (ittvax!swatt). fixed this obnoxious
- * routine to NOT read all the way through the damned directory
- * "stat"'ing every file in sight just to get 10 names!!!
- *
- * It still reads through the directory from the beginning until
- * the list is filled, but this is only once every LLEN names.
  */
 
 /* LOCAL only */
  */
 
 /* LOCAL only */
@@ -134,10 +122,9 @@ char *reqst;
 register char *dir, *pre;
 {
        static DIR  *dirp = NULL;
 register char *dir, *pre;
 {
        static DIR  *dirp = NULL;
-       register nfound;
-       char filename[NAMESIZE];
-       int plen = strlen (pre);
-       int flen;
+       register struct direct *dentp;
+       register int i;
+       int plen = strlen(pre);
        extern char MaxGrade;
 
        if (dirp == NULL) {
        extern char MaxGrade;
 
        if (dirp == NULL) {
@@ -145,10 +132,11 @@ register char *dir, *pre;
                        DEBUG(1,"opendir(%s) FAILS\n",subdir(dir,pre[0]));
                        return 0;
                }
                        DEBUG(1,"opendir(%s) FAILS\n",subdir(dir,pre[0]));
                        return 0;
                }
-       }
-       else
+       } else
                rewinddir(dirp);
                rewinddir(dirp);
-       for (nfound = 0, Nfiles = 0; gnamef(dirp, filename);) {
+
+       Nfiles = 0;
+       while ((dentp = readdir(dirp)) != NULL && Nfiles < LLEN) {
                /* Check for two systems with the same prefix.
                 * Magic number "5" is 1 for "grade" character plus
                 * 4 for sequence number.  The point here is to not
                /* Check for two systems with the same prefix.
                 * Magic number "5" is 1 for "grade" character plus
                 * 4 for sequence number.  The point here is to not
@@ -157,53 +145,44 @@ register char *dir, *pre;
                 * Special case: prefix "X." does not do this check
                 * so uuxqt can use bldflst.
                 */
                 * Special case: prefix "X." does not do this check
                 * so uuxqt can use bldflst.
                 */
-               flen = strlen(filename);
-               if (!prefix(pre, filename) || (plen != 2 && flen-plen != 5)) {
-                       DEBUG(99,"bldflst rejects %s\n",filename);
+               if (!prefix(pre, dentp->d_name) ||
+                       (plen != 2 && (dentp->d_namlen-plen) != 5)) {
+                       DEBUG(99,"bldflst rejects %s\n",dentp->d_name);
                        continue;
                }
                        continue;
                }
-               if (filename[flen-5] > MaxGrade ) {
-                       DEBUG(8,"bldflst rejects %s, grade too low\n",filename);
+               if (dentp->d_name[dentp->d_namlen-5] > MaxGrade) {
+                       DEBUG(8, "bldflst rejects %s, grade too low\n",
+                               dentp->d_name);
                        continue;
                }
                        continue;
                }
-               nfound++;
                if (*reqst == 'c')
                        return 1;
                if (*reqst == 'c')
                        return 1;
-               entflst(filename);
-       }
-       return  nfound? 1: 0;
-}
 
 
-/***
- *     entflst - put new name if list is not full
- *               or new name is less than the MAX
- *               now in the list.
- *     Nfiles, Filent[] are modified.
- *     return value - none
- *
- */
+               /* locate position for the new file and make room for it */
+               for (i = Nfiles; i > 0; i--) {
+                       if (pcompar(dentp->d_name, Filent[i-1]) <= 0)
+                               break;
+                       if (i <LLEN)
+                               strcpy(Filent[i], Filent[i-1]);
+               }
 
 
-/* LOCAL only */
-int
-entflst(file)
-register char *file;
-{
-       register int i;
+               /* add new file (if there is room), and increase Nfiles if need be */
+               if (i < LLEN) {
+                       DEBUG(99,"bldflst accepts %s",dentp->d_name);
+                       DEBUG(99," as Filent[%d]\n", i);
+                       strcpy(Filent[i], dentp->d_name);
+                       if (Nfiles < LLEN)
+                               Nfiles++;
+               } else
+                       DEBUG(99,"Filent full, %s rejected by bldflst\n", dentp->d_name);
+               
 
 
-       /* locate position for the new file and make room for it */
-       for (i = Nfiles; i > 0; i--) {
-               if (pcompar(file, Filent[i-1]) >= 0)
-                       break;
-               if (i <LLEN)
-                       strcpy(Filent[i], Filent[i-1]);
        }
        }
+       if (Debug >99)
+               for(i=0;i<Nfiles;i++)
+                       fprintf(stderr,"Filent[%d]=%s\n",i,Filent[i]);
 
 
-       /* add new file (if there is room), and increase Nfiles if need be */
-       if (i < LLEN) {
-               strcpy(Filent[i], file);
-               if (Nfiles < LLEN)
-                       Nfiles++;
-       }
+       return Nfiles > 0;
 }
 
 /*
 }
 
 /*
@@ -217,13 +196,12 @@ register char *file;
  *
  */
 /* LOCAL only */
  *
  */
 /* LOCAL only */
-int
 pcompar(p1, p2)
 register char *p1, *p2;
 {
        register int rc;
 
 pcompar(p1, p2)
 register char *p1, *p2;
 {
        register int rc;
 
-       /* assert: strlen(p1) and strlen(p2) are >= 5 */
+       /* strlen(p1) and strlen(p2) are >= 5 */
        p1 += strlen(p1)-5;
        p2 += strlen(p2)-5;
        /* check 'grade' */
        p1 += strlen(p1)-5;
        p2 += strlen(p2)-5;
        /* check 'grade' */
@@ -239,30 +217,8 @@ register char *p1, *p2;
        return strcmp(p2, p1);
 }
 
        return strcmp(p2, p1);
 }
 
-/***
- *     gtwrkf - get next work file
- *      Nfiles, Filent[] are modified.
- *
- *     return value:
- *
- *             0  - No file gotten
- *             1  - File successfully gotten.
- *
- */
-
-/* LOCAL only */
-gtwrkf(dir, file)
-char *file, *dir;
-{
-       if (Nfiles <= 0)
-               return 0;
-       sprintf(file, "%s/%s", dir, Filent[--Nfiles]);
-       return 1;
-}
-
-/***
- *     gtwvec(file, dir, wkpre, wrkvec)        get work vector
- *     char *file, *dir, *wkpre, **wrkvec;
+/*
+ *     get work vector
  *
  *     return codes:
  *             positive number  -  number of arguments
  *
  *     return codes:
  *             positive number  -  number of arguments
@@ -285,10 +241,7 @@ register char *file;
        return nargs;
 }
 
        return nargs;
 }
 
-/***
- *     iswrk(file, reqst, dir, pre)
- *     char *file, *reqst, *dir, *pre;
- *
+/*
  *     iswrk  -  this routine will check the work list (list).
  *     If it is empty or the present work is exhausted, it
  *     will call bldflst to generate a new list.
  *     iswrk  -  this routine will check the work list (list).
  *     If it is empty or the present work is exhausted, it
  *     will call bldflst to generate a new list.
@@ -307,52 +260,52 @@ iswrk(file, reqst, dir, pre)
 register char *file, *reqst, *dir, *pre;
 {
        static char *lastpre = 0;
 register char *file, *reqst, *dir, *pre;
 {
        static char *lastpre = 0;
-       register ret;
+       register ret = 0;
+       int i;
 
        /* Starting new system; re-init */
 
        /* Starting new system; re-init */
-       if (lastpre == 0 || strcmp(lastpre,pre) != 0) {
-               anlwrk ("", (char **)0);        /* Force close of work file */
+       if (lastpre == 0 || strcmp(lastpre, pre) != SAME) {
+               /* Force close of work file */
+               anlwrk("", (char **)0);
 
                /* Save last worked-on prefix */
                if (lastpre != 0)
 
                /* Save last worked-on prefix */
                if (lastpre != 0)
-                       free (lastpre);
+                       free(lastpre);
                lastpre = malloc((unsigned)(strlen(pre)+1));
                lastpre = malloc((unsigned)(strlen(pre)+1));
-               strcpy (lastpre, pre);
+               strcpy(lastpre, pre);
 
 
-               /* Set the external indexes properly
-                */
+               /* Set the external indexes properly */
                Nfiles = 0;
        }
 
                Nfiles = 0;
        }
 
-       /* If the list is empty or new files have entered
+       /*
+        * If the list is empty or new files have entered
         * the spool area, call "bldflst" to read
         * the spool area, call "bldflst" to read
-        * some file names into it.  Because names can
-        * be put in the list that later turn out to
-        * be unusable (from "gtwrkf"), this operation
-        * continues until either "bldflst" can't find
-        * any new files, or "gtwrkf" signals success.
+        * some file names into it. 
         */
         */
-       for (;;) {
-               ret = 0;
-               if (Nfiles == 0 || newspool((time_t)TLIMIT)) {
-                       ret = bldflst (reqst, dir, pre);
-                       DEBUG(99,"bldflst returns %d\n",ret);
-               }
-
-               /* If they only wanted to check, return
-                * boolean list not empty.  NB: the list
-                * will be forcibly emptied as soon as
-                * a new system name is mentioned.
-                */
-               if (*reqst == 'c')
-                       return ret;
+       if (Nfiles <= 0 || newspool((time_t)TLIMIT)) {
+               ret = bldflst(reqst, dir, pre);
+               DEBUG(99, "bldflst returns %d\n", ret);
+       }
 
 
-               if (Nfiles == 0)
-                       return 0;
+       /* If they only wanted to check, return
+        * boolean list not empty.  NB: the list
+        * will be forcibly emptied as soon as
+        * a new system name is mentioned.
+        */
+       if (*reqst == 'c')
+               return ret;
 
 
-               if (gtwrkf(dir, file))
-                       return 1;
+       if (Nfiles-- <= 0) {
+               /* Didn't find any files in the spool area */
+               Nfiles = 0;
+               return 0;
        }
        }
+       /* Found some files, return the first one */
+       sprintf(file, "%s/%s", dir, Filent[0]);
+       for (i = 0; i < Nfiles; i++)
+               strcpy(Filent[i], Filent[i+1]);
+       return 1;
 }
 
 /* Return non-zero if there is new work in the spool
 }
 
 /* Return non-zero if there is new work in the spool