chiark / gitweb /
REORG Delete everything that's not innduct or build system or changed for innduct
[innduct.git] / backends / archive.c
diff --git a/backends/archive.c b/backends/archive.c
deleted file mode 100644 (file)
index 73a7970..0000000
+++ /dev/null
@@ -1,653 +0,0 @@
-/*  $Id: archive.c 6138 2003-01-19 04:13:51Z rra $
-**
-**  Read batchfiles on standard input and archive them.
-*/
-
-#include "config.h"
-#include "clibrary.h"
-#include <ctype.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <time.h>
-
-#ifdef TM_IN_SYS_TIME
-# include <sys/time.h>
-#endif
-
-#include "inn/innconf.h"
-#include "inn/messages.h"
-#include "inn/wire.h"
-#include "libinn.h"
-#include "paths.h"
-#include "storage.h"
-
-
-static char    *Archive = NULL;
-static char    *ERRLOG = NULL;
-
-/*
-**  Return a YYYYMM string that represents the current year/month
-*/
-static char *
-DateString(void)
-{
-    static char                ds[10];
-    time_t             now;
-    struct tm          *x;
-
-    time(&now);
-    x = localtime(&now);
-    snprintf(ds, sizeof(ds), "%d%d", x->tm_year + 1900, x->tm_mon + 1);
-
-    return ds;
-}
-
-
-/*
-**  Try to make one directory.  Return false on error.
-*/
-static bool
-MakeDir(char *Name)
-{
-    struct stat                Sb;
-
-    if (mkdir(Name, GROUPDIR_MODE) >= 0)
-       return true;
-
-    /* See if it failed because it already exists. */
-    return stat(Name, &Sb) >= 0 && S_ISDIR(Sb.st_mode);
-}
-
-
-/*
-**  Given an entry, comp/foo/bar/1123, create the directory and all
-**  parent directories needed.  Return false on error.
-*/
-static bool
-MakeArchiveDirectory(char *Name)
-{
-    char       *p;
-    char       *save;
-    bool               made;
-
-    if ((save = strrchr(Name, '/')) != NULL)
-       *save = '\0';
-
-    /* Optimize common case -- parent almost always exists. */
-    if (MakeDir(Name)) {
-       if (save)
-           *save = '/';
-       return true;
-    }
-
-    /* Try to make each of comp and comp/foo in turn. */
-    for (p = Name; *p; p++)
-       if (*p == '/' && p != Name) {
-           *p = '\0';
-           made = MakeDir(Name);
-           *p = '/';
-           if (!made) {
-               if (save)
-                   *save = '/';
-               return false;
-           }
-       }
-
-    made = MakeDir(Name);
-    if (save)
-       *save = '/';
-    return made;
-}
-
-
-/*
-**  Copy a file.  Return false if error.
-*/
-static bool
-Copy(char *src, char *dest)
-{
-    FILE       *in;
-    FILE       *out;
-    size_t     i;
-    char       *p;
-    char       buff[BUFSIZ];
-
-    /* Open the output file. */
-    if ((out = fopen(dest, "w")) == NULL) {
-       /* Failed; make any missing directories and try again. */
-       if ((p = strrchr(dest, '/')) != NULL) {
-           if (!MakeArchiveDirectory(dest)) {
-                syswarn("cannot mkdir for %s", dest);
-               return false;
-           }
-           out = fopen(dest, "w");
-       }
-       if (p == NULL || out == NULL) {
-            syswarn("cannot open %s for writing", dest);
-           return false;
-       }
-    }
-
-    /* Opening the input file is easier. */
-    if ((in = fopen(src, "r")) == NULL) {
-        syswarn("cannot open %s for reading", src);
-       fclose(out);
-       unlink(dest);
-       return false;
-    }
-
-    /* Write the data. */
-    while ((i = fread(buff, 1, sizeof buff, in)) != 0)
-       if (fwrite(buff, 1, i, out) != i) {
-            syswarn("cannot write to %s", dest);
-           fclose(in);
-           fclose(out);
-           unlink(dest);
-           return false;
-       }
-    fclose(in);
-
-    /* Flush and close the output. */
-    if (ferror(out) || fflush(out) == EOF) {
-        syswarn("cannot flush %s", dest);
-       unlink(dest);
-       fclose(out);
-       return false;
-    }
-    if (fclose(out) == EOF) {
-        syswarn("cannot close %s", dest);
-       unlink(dest);
-       return false;
-    }
-
-    return true;
-}
-
-
-/*
-**  Copy an article from memory into a file.
-*/
-static bool
-CopyArt(ARTHANDLE *art, char *dest, bool Concat)
-{
-    FILE       *out;
-    const char         *p;
-    char               *q, *article;
-    size_t             i;
-    const char         *mode = "w";
-
-    if (Concat) mode = "a";
-
-    /* Open the output file. */
-    if ((out = fopen(dest, mode)) == NULL) {
-       /* Failed; make any missing directories and try again. */
-       if ((p = strrchr(dest, '/')) != NULL) {
-           if (!MakeArchiveDirectory(dest)) {
-                syswarn("cannot mkdir for %s", dest);
-               return false;
-           }
-           out = fopen(dest, mode);
-       }
-       if (p == NULL || out == NULL) {
-            syswarn("cannot open %s for writing", dest);
-           return false;
-       }
-    }
-
-    /* Copy the data. */
-    article = xmalloc(art->len);
-    for (i=0, q=article, p=art->data; p<art->data+art->len;) {
-       if (&p[1] < art->data + art->len && p[0] == '\r' && p[1] == '\n') {
-           p += 2;
-           *q++ = '\n';
-           i++;
-           if (&p[1] < art->data + art->len && p[0] == '.' && p[1] == '.') {
-               p += 2;
-               *q++ = '.';
-               i++;
-           }
-           if (&p[2] < art->data + art->len && p[0] == '.' && p[1] == '\r' && p[2] == '\n') {
-               break;
-           }
-       } else {
-           *q++ = *p++;
-           i++;
-       }
-    }
-    *q++ = '\0';
-
-    /* Write the data. */
-    if (Concat) {
-       /* Write a separator... */
-       fprintf(out, "-----------\n");
-    }
-    if (fwrite(article, i, 1, out) != 1) {
-        syswarn("cannot write to %s", dest);
-       fclose(out);
-       if (!Concat) unlink(dest);
-       free(article);
-       return false;
-    }
-    free(article);
-
-    /* Flush and close the output. */
-    if (ferror(out) || fflush(out) == EOF) {
-        syswarn("cannot flush %s", dest);
-       if (!Concat) unlink(dest);
-       fclose(out);
-       return false;
-    }
-    if (fclose(out) == EOF) {
-        syswarn("cannot close %s", dest);
-       if (!Concat) unlink(dest);
-       return false;
-    }
-
-    return true;
-}
-
-
-/*
-**  Write an index entry.  Ignore I/O errors; our caller checks for them.
-*/
-static void
-WriteArtIndex(ARTHANDLE *art, char *ShortName)
-{
-    const char *p;
-    int        i;
-    char               Subject[BUFSIZ];
-    char               MessageID[BUFSIZ];
-
-    Subject[0] = '\0';         /* default to null string */
-    p = wire_findheader(art->data, art->len, "Subject");
-    if (p != NULL) {
-       for (i=0; *p != '\r' && *p != '\n' && *p != '\0'; i++) {
-           Subject[i] = *p++;
-       }
-       Subject[i] = '\0';
-    }
-
-    MessageID[0] = '\0';       /* default to null string */
-    p = wire_findheader(art->data, art->len, "Message-ID");
-    if (p != NULL) {
-       for (i=0; *p != '\r' && *p != '\n' && *p != '\0'; i++) {
-           MessageID[i] = *p++;
-       }
-       MessageID[i] = '\0';
-    }
-
-    printf("%s %s %s\n",
-           ShortName,
-           MessageID[0] ? MessageID : "<none>",
-           Subject[0] ? Subject : "<none>");
-}
-
-
-/*
-** Crack an Xref line apart into separate strings, each of the form "ng:artnum".
-** Return in "lenp" the number of newsgroups found.
-** 
-** This routine blatantly stolen from tradspool.c
-*/
-static char **
-CrackXref(const char *xref, unsigned int *lenp) {
-    char *p;
-    char **xrefs;
-    char *q;
-    unsigned int len, xrefsize;
-
-    len = 0;
-    xrefsize = 5;
-    xrefs = xmalloc(xrefsize * sizeof(char *));
-
-    /* skip pathhost */
-    if ((p = strchr(xref, ' ')) == NULL) {
-        warn("cannot find pathhost in Xref header");
-       return NULL;
-    }
-    /* skip next spaces */
-    for (p++; *p == ' ' ; p++) ;
-    while (true) {
-       /* check for EOL */
-       /* shouldn't ever hit null w/o hitting a \r\n first, but best to be paranoid */
-       if (*p == '\n' || *p == '\r' || *p == 0) {
-           /* hit EOL, return. */
-           *lenp = len;
-           return xrefs;
-       }
-       /* skip to next space or EOL */
-       for (q=p; *q && *q != ' ' && *q != '\n' && *q != '\r' ; ++q) ;
-
-        xrefs[len] = xstrndup(p, q - p);
-
-       if (++len == xrefsize) {
-           /* grow xrefs if needed. */
-           xrefsize *= 2;
-            xrefs = xrealloc(xrefs, xrefsize * sizeof(char *));
-       }
-
-       p = q;
-       /* skip spaces */
-       for ( ; *p == ' ' ; p++) ;
-    }
-}
-
-
-/*
-** Crack an groups pattern parameter apart into separate strings
-** Return in "lenp" the number of patterns found.
-*/
-static char **
-CrackGroups(char *group, unsigned int *lenp) {
-    char *p;
-    char **groups;
-    char *q;
-    unsigned int len, grpsize;
-
-    len = 0;
-    grpsize = 5;
-    groups = xmalloc(grpsize * sizeof(char *));
-
-    /* skip leading spaces */
-    for (p=group; *p == ' ' ; p++) ;
-    while (true) {
-       /* check for EOL */
-       /* shouldn't ever hit null w/o hitting a \r\n first, but best to be paranoid */
-       if (*p == '\n' || *p == '\r' || *p == 0) {
-           /* hit EOL, return. */
-           *lenp = len;
-           return groups;
-       }
-       /* skip to next comma, space, or EOL */
-       for (q=p; *q && *q != ',' && *q != ' ' && *q != '\n' && *q != '\r' ; ++q) ;
-
-        groups[len] = xstrndup(p, q - p);
-
-       if (++len == grpsize) {
-           /* grow groups if needed. */
-           grpsize *= 2;
-            groups = xrealloc(groups, grpsize * sizeof(char *));
-       }
-
-       p = q;
-       /* skip commas and spaces */
-       for ( ; *p == ' ' || *p == ',' ; p++) ;
-    }
-}
-
-
-int
-main(int ac, char *av[])
-{
-    char       *Name;
-    char       *p;
-    FILE       *F;
-    int        i;
-    bool               Flat;
-    bool               Redirect;
-    bool               Concat;
-    char               *Index;
-    char               buff[BUFSIZ];
-    char               *spool;
-    char               dest[BUFSIZ];
-    char               **groups, *q, *ng;
-    char               **xrefs;
-    const char         *xrefhdr;
-    ARTHANDLE          *art;
-    TOKEN              token;
-    unsigned int       numgroups, numxrefs;
-    int                        j;
-    char               *base = NULL;
-    bool               doit;
-
-    /* First thing, set up our identity. */
-    message_program_name = "archive";
-
-    /* Set defaults. */
-    if (!innconf_read(NULL))
-        exit(1);
-    Concat = false;
-    Flat = false;
-    Index = NULL;
-    Redirect = true;
-    umask(NEWSUMASK);
-    ERRLOG = concatpath(innconf->pathlog, _PATH_ERRLOG);
-    Archive = innconf->patharchive;
-    groups = NULL;
-    numgroups = 0;
-
-    /* Parse JCL. */
-    while ((i = getopt(ac, av, "a:cfi:p:r")) != EOF)
-       switch (i) {
-       default:
-            die("usage error");
-            break;
-       case 'a':
-           Archive = optarg;
-           break;
-       case 'c':
-           Flat = true;
-           Concat = true;
-           break;
-       case 'f':
-           Flat = true;
-           break;
-       case 'i':
-           Index = optarg;
-           break;
-       case 'p':
-           groups = CrackGroups(optarg, &numgroups);
-           break;
-       case 'r':
-           Redirect = false;
-           break;
-       }
-
-    /* Parse arguments -- at most one, the batchfile. */
-    ac -= optind;
-    av += optind;
-    if (ac > 2)
-        die("usage error");
-
-    /* Do file redirections. */
-    if (Redirect)
-       freopen(ERRLOG, "a", stderr);
-    if (ac == 1 && freopen(av[0], "r", stdin) == NULL)
-        sysdie("cannot open %s for input", av[0]);
-    if (Index && freopen(Index, "a", stdout) == NULL)
-        sysdie("cannot open %s for output", Index);
-
-    /* Go to where the action is. */
-    if (chdir(innconf->patharticles) < 0)
-        sysdie("cannot chdir to %s", innconf->patharticles);
-
-    /* Set up the destination. */
-    strcpy(dest, Archive);
-    Name = dest + strlen(dest);
-    *Name++ = '/';
-
-    if (!SMinit())
-        die("cannot initialize storage manager: %s", SMerrorstr);
-
-    /* Read input. */
-    while (fgets(buff, sizeof buff, stdin) != NULL) {
-       if ((p = strchr(buff, '\n')) == NULL) {
-            warn("skipping %.40s: too long", buff);
-           continue;
-       }
-       *p = '\0';
-       if (buff[0] == '\0' || buff[0] == '#')
-           continue;
-
-       /* Check to see if this is a token... */
-       if (IsToken(buff)) {
-           /* Get a copy of the article. */
-           token = TextToToken(buff);
-           if ((art = SMretrieve(token, RETR_ALL)) == NULL) {
-                warn("cannot retrieve %s", buff);
-               continue;
-           }
-
-           /* Determine groups from the Xref header */
-           xrefhdr = wire_findheader(art->data, art->len, "Xref");
-           if (xrefhdr == NULL) {
-                warn("cannot find Xref header");
-               SMfreearticle(art);
-               continue;
-           }
-
-           if ((xrefs = CrackXref(xrefhdr, &numxrefs)) == NULL || numxrefs == 0) {
-                warn("bogus Xref header");
-               SMfreearticle(art);
-               continue;
-           }
-
-           /* Process each newsgroup... */
-           if (base) {
-               free(base);
-               base = NULL;
-           }
-           for (i=0; (unsigned)i<numxrefs; i++) {
-               /* Check for group limits... -p flag */
-               if ((p=strchr(xrefs[i], ':')) == NULL) {
-                    warn("bogus Xref entry %s", xrefs[i]);
-                   continue;   /* Skip to next xref */
-               }
-               if (numgroups > 0) {
-                   *p = '\0';
-                   ng = xrefs[i];
-                   doit = false;
-                   for (j=0; (unsigned)j<numgroups && !doit; j++) {
-                       if (uwildmat(ng, groups[j]) != 0) doit=true;
-                   }
-               }
-               else {
-                   doit = true;
-               }
-               *p = '/';
-               if (doit) {
-                   p = Name;
-                   q = xrefs[i];
-                   while(*q) {
-                       *p++ = *q++;
-                   }
-                   *p='\0';
-
-                   if (!Flat) {
-                       for (p=Name; *p; p++) {
-                           if (*p == '.') {
-                               *p = '/';
-                           }
-                       }
-                   }
-
-                   if (Concat) {
-                       p = strrchr(Name, '/');
-                       q = DateString();
-                       p++;
-                       while (*q) {
-                           *p++ = *q++;
-                       }
-                       *p = '\0';
-                   }
-                       
-                   if (base && !Concat) {
-                       /* Try to link the file into the archive. */
-                       if (link(base, dest) < 0) {
-
-                           /* Make the archive directory. */
-                           if (!MakeArchiveDirectory(dest)) {
-                                syswarn("cannot mkdir for %s", dest);
-                               continue;
-                           }
-
-                           /* Try to link again; if that fails, make a copy. */
-                           if (link(base, dest) < 0) {
-#if    defined(HAVE_SYMLINK)
-                               if (symlink(base, dest) < 0)
-                                    syswarn("cannot symlink %s to %s",
-                                            dest, base);
-                               else
-#endif /* defined(HAVE_SYMLINK) */
-                               if (!Copy(base, dest))
-                                   continue;
-                               continue;
-                           }
-                       }
-                   } else {
-                       if (!CopyArt(art, dest, Concat))
-                            syswarn("copying %s to %s failed", buff, dest);
-                       base = xstrdup(dest);
-                   }
-
-                   /* Write index. */
-                   if (Index) {
-                       WriteArtIndex(art, Name);
-                       if (ferror(stdout) || fflush(stdout) == EOF)
-                            syswarn("cannot write index for %s", Name);
-                   }
-               }
-           }
-
-           /* Free up the article storage space */
-           SMfreearticle(art);
-           art = NULL;
-           /* Free up the xrefs storage space */
-           for ( i=0; (unsigned)i<numxrefs; i++) free(xrefs[i]);
-           free(xrefs);
-           numxrefs = 0;
-           xrefs = NULL;
-       } else {
-            warn("%s is not a token", buff);
-           continue;
-       }
-    }
-
-    /* close down the storage manager api */
-    SMshutdown();
-
-    /* If we read all our input, try to remove the file, and we're done. */
-    if (feof(stdin)) {
-       fclose(stdin);
-       if (av[0])
-           unlink(av[0]);
-       exit(0);
-    }
-
-    /* Make an appropriate spool file. */
-    p = av[0];
-    if (p == NULL)
-        spool = concatpath(innconf->pathoutgoing, "archive");
-    else if (*p == '/')
-        spool = concat(p, ".bch", (char *) 0);
-    else
-        spool = concat(innconf->pathoutgoing, "/", p, ".bch", (char *) 0);
-    if ((F = xfopena(spool)) == NULL)
-        sysdie("cannot spool to %s", spool);
-
-    /* Write the rest of stdin to the spool file. */
-    i = 0;
-    if (fprintf(F, "%s\n", buff) == EOF) {
-        syswarn("cannot start spool");
-       i = 1;
-    }
-    while (fgets(buff, sizeof buff, stdin) != NULL) 
-       if (fputs(buff, F) == EOF) {
-            syswarn("cannot write to spool");
-           i = 1;
-           break;
-       }
-    if (fclose(F) == EOF) {
-        syswarn("cannot close spool");
-       i = 1;
-    }
-
-    /* If we had a named input file, try to rename the spool. */
-    if (p != NULL && rename(spool, av[0]) < 0) {
-        syswarn("cannot rename spool");
-       i = 1;
-    }
-
-    exit(i);
-    /* NOTREACHED */
-}