"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. For more information about "applyfilter.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.11.12_vs_1.12.0.

    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 }