"Fossies" - the Fresh Open Source Software Archive

Member "leafnode-1.12.0/applyfilter.c" (28 Dec 2021, 6620 Bytes) of package /linux/misc/leafnode-1.12.0.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2  * apply filter file to all files in a newsgroup
    3  *
    4  * Written by Cornelius Krasel <krasel@wpxx02.toxi.uni-wuerzburg.de>.
    5  * Copyright 1999.
    6  *
    7  * Modified and copyright of the modifications 2002 by Matthias Andree
    8  * <matthias.andree@gmx.de> and Ralf Wildenhues <ralf.wildenhues@gmx.de>
    9  *
   10  * Modified and copyright of the modifications 2002 - 2021 by Matthias Andree
   11  *
   12  * See file COPYING for restrictions on the use of this software.
   13  */
   14 
   15 #include "leafnode.h"
   16 #include "ln_log.h"
   17 
   18 #include <sys/stat.h>
   19 #include <sys/types.h>
   20 #include <ctype.h>
   21 #include "system.h"
   22 #include <stdio.h>
   23 #include <stdlib.h>
   24 #include <string.h>
   25 #include <unistd.h>
   26 #include <utime.h>
   27 
   28 #define MAXHEADERSIZE 2047
   29 
   30 int debug = 0;
   31 int verbose;
   32 
   33 /* read from file f into malloced buffer *bufp of size *size
   34  * up to delim or EOF.  Buffer is adjusted to fit input.
   35  * return pointer to match or end of file, NULL in case of error
   36  */
   37 static /*@null@*/ /*@dependent@*/ char *
   38 readtodelim(FILE *f, const char *name, /*@unique@*/ /*@observer@*/ const char *delim,
   39     char **bufp, size_t *size)
   40 {
   41     size_t dlen = strlen(delim) - 1;
   42     size_t nread, res;
   43     char *k;
   44 
   45     nread = 0;
   46     if (*size < 1 || *bufp == NULL)
   47     *bufp = critmalloc((*size = MAXHEADERSIZE), "readtodelim");
   48 
   49     /*@+loopexec@*/
   50     for (;;) {
   51     res = fread(*bufp + nread, 1, *size - nread - 1, f);
   52     (*bufp)[nread + res] = '\0';
   53     /* skip as much as possible */
   54     k = strstr(nread > dlen ? *bufp + nread - dlen : *bufp, delim);
   55     if (ferror(f)) {
   56         printf("error reading %s\n", name);
   57         clearerr(f);
   58         return k;
   59     }
   60     nread += res;
   61     if (feof(f)) {
   62         clearerr(f);
   63         return k != NULL ? k : *bufp + nread;
   64     }
   65     if (k != NULL) {
   66         return k;
   67     }
   68     /* must read more */
   69     *bufp = critrealloc(*bufp, (*size)*=2, "readtodelim");
   70     }
   71     /*@=loopexec@*/
   72 }
   73 
   74 /** unfold a header string \a t in-place.
   75  *  CRLF are converted to LF. */
   76 static void unfold(char *t)
   77 {
   78     char *i;
   79 
   80     for (i = t; *i ; i++) {
   81     if (i[0] == '\r' && i[1] == '\n')
   82         continue;
   83     if (i[0] == '\n'
   84         && (i[1] == ' ' || i[1] == '\t'))
   85         continue;
   86     *t = *i;
   87     t++;
   88     }
   89     *t = '\0';
   90 }
   91 
   92 /* read article headers, cut off body
   93  * return 0 for success, -1 for error, -2 for article without body
   94  */
   95 static int
   96 readheaders(FILE *f, /*@unique@*/ const char *name, char **bufp, size_t *size)
   97 {
   98     char *k = readtodelim(f, name, "\n\n", bufp, size);
   99     if (k != NULL) {
  100     /* unfold lines */
  101     unfold(*bufp);
  102     if (*k == '\0')
  103         return -2;
  104     else {
  105         k[1] = '\0';
  106         return 0;
  107     }
  108     } else {
  109     return -1;
  110     }
  111 }
  112 
  113 int
  114 main(int argc, char *argv[])
  115 {
  116     const char c[] = "-\\|/";
  117     int i, score, option, deleted, kept;
  118     unsigned long n;
  119     char *msgid;
  120     char *l;
  121     size_t lsize;
  122     const char *msgidpath = "";
  123     FILE *f;
  124     DIR *d;
  125     struct dirent *de;
  126     struct stat st;
  127     struct utimbuf u;
  128     struct newsgroup *g;
  129 
  130     myopenlog("applyfilter");
  131 
  132     if (!initvars(argv[0]))
  133     exit(1);
  134 
  135     while ((option = getopt(argc, argv, "v")) != -1) {
  136     if (option == 'v')
  137         verbose++;
  138     else {
  139         printf("Usage: %s newsgroup\n", argv[0]);
  140         exit(1);
  141     }
  142     }
  143 
  144     if (argv[optind] == NULL) {
  145     printf("Usage: %s newsgroup\n", argv[0]);
  146     exit(1);
  147     }
  148 
  149     if (!readconfig(0)) {
  150     printf("Reading configuration failed, exiting "
  151            "(see syslog for more information).\n");
  152     exit(2);
  153     }
  154     freeservers();
  155 
  156     if (filterfile)
  157     readfilter(filterfile);
  158     else {
  159     printf("Nothing to filter -- no filterfile found.\n");
  160     freeconfig();
  161     exit(0);
  162     }
  163 
  164     if (try_lock(timeout_lock)) {
  165     printf("Cannot obtain lock file, aborting.\n");
  166     exit(1);
  167     }
  168 
  169     readactive();
  170     if (!active) {
  171     printf("Problem reading active file.\n");
  172     freeconfig();
  173     exit(1);
  174     }
  175 
  176     g = findgroup(argv[optind]);
  177     if (!g) {
  178     printf("Newsgroups %s not found in active file.\n", argv[optind]);
  179     unlink(lockfile);
  180     exit(1);
  181     }
  182 
  183     /* to automatically rise the low water mark, we reset g->first to
  184      * ULONG_MAX. */
  185     g->first = ULONG_MAX;
  186     /* We used to do g->last = 0; but that can severely confuse news
  187      * readers, we don't ever want to decrease the high water mark. */
  188     if (!chdirgroup(g->name, FALSE)) {
  189     printf("No such newsgroup: %s\n", g->name);
  190     unlink(lockfile);
  191     exit(1);
  192     }
  193     if (!(d = opendir("."))) {
  194     printf("Unable to open directory for newsgroup %s\n", g->name);
  195     unlink(lockfile);
  196     exit(1);
  197     }
  198 
  199     i = 0;
  200     deleted = 0;
  201     kept = 0;
  202     lsize = MAXHEADERSIZE + 1;
  203     l = critmalloc(lsize, "Space for article");
  204     while ((de = readdir(d)) != NULL) {
  205     if (!isdigit((unsigned char)de->d_name[0])) {
  206         /* no need to stat file */
  207         continue;
  208     }
  209     switch (verbose) {
  210     case 1:{
  211         printf("%c\b", c[i % 4]);
  212         fflush(stdout);
  213         i++;
  214         break;
  215         }
  216     case 2:{
  217         printf("%s\n", de->d_name);
  218         }
  219     }
  220     if ((f = fopen(de->d_name, "r")) != NULL
  221         && fstat(fileno(f), &st) == 0
  222         && S_ISREG(st.st_mode))
  223     {
  224         switch (readheaders(f, de->d_name, &l, &lsize)) {
  225         case 0:
  226         case -2:
  227             score = dofilter((unsigned char *)l);
  228             break;
  229         case -1:
  230             score = -1; /* FIXME: how to handle read error? */
  231             break;
  232         default:
  233             /* this branch will never be executed, but
  234              * eliminates a compiler warning */
  235             score = 0;
  236             break;
  237         }
  238 
  239         if (score) {
  240         msgid = fgetheader(f, "Message-ID:");
  241         fclose(f);
  242         unlink(de->d_name);
  243         /* delete stuff in message.id directory as well */
  244         if (msgid) {
  245             msgidpath = lookup(msgid);
  246             if ((stat(msgidpath, &st) == 0) /* RATS: ignore */
  247                     && (st.st_nlink < 2)) {
  248             if (unlink(msgidpath) == 0)
  249                 deleted++;
  250             }
  251             free(msgid);
  252         }
  253         if (verbose)
  254             printf("%s %s deleted\n", de->d_name, msgidpath);
  255         } else {
  256         fclose(f);
  257         n = strtoul(de->d_name, NULL, 10);
  258         if (n) {
  259             if (n < g->first)
  260             g->first = n;
  261             if (n > g->last)
  262             g->last = n;
  263         }
  264         u.actime = st.st_atime;
  265         u.modtime = st.st_mtime;
  266         utime(de->d_name, &u);
  267         kept++;
  268         }
  269     } else {
  270         if (f) {
  271         ln_log(LNLOG_SERR, LNLOG_CARTICLE, 
  272             "could not stat %s or not a regular file\n",
  273             de->d_name);
  274         (void)fclose(f);
  275         } else {
  276         ln_log(LNLOG_SERR, LNLOG_CARTICLE, "could not open %s\n",
  277             de->d_name);
  278         }
  279     }
  280     }
  281     closedir(d);
  282     free(l);
  283     if (g->first > g->last) {
  284     /* group is empty */
  285     g->first = g->last + 1;
  286     }
  287     if (writeactive()) ln_log(LNLOG_SERR, LNLOG_CTOP, "Error writing groupinfo.");
  288     freeactive(active);
  289     unlink(lockfile);
  290     printf("%d article%s deleted, %d kept.\n", deleted, PLURAL(deleted), kept);
  291 
  292     if (verbose)
  293     printf("Updating .overview file\n");
  294     getxover();
  295     freexover();
  296     freeconfig();
  297     exit(0);
  298 }