home *** CD-ROM | disk | FTP | other *** search
/ Beijing Paradise BBS Backup / PARADISE.ISO / software / BBSDOORW / SNWS191S.ZIP / EXPIRE.C < prev    next >
Text File  |  1993-08-16  |  10KB  |  383 lines

  1. /*
  2.     SNEWS 1.91
  3.  
  4.     EXPIRE - expire news database articles by number of days since rx'd
  5.  
  6.  
  7.     Copyright (C) 1991  John McCombs, PO Box 2708, Christchurch, NEW ZEALAND
  8.                         john@ahuriri.gen.nz
  9.  
  10.     Modifications copyright (C) 1993  Daniel Fandrich
  11.                         <dan@fch.wimsey.bc.ca> or CompuServe 72365,306
  12.  
  13.     This program is free software; you can redistribute it and/or modify
  14.     it under the terms of the GNU General Public License, version 1, as
  15.     published by the Free Software Foundation.
  16.  
  17.     This program is distributed in the hope that it will be useful,
  18.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.     GNU General Public License for more details.
  21.  
  22.     See the file COPYING, which contains a copy of the GNU General
  23.     Public License.
  24.  
  25.  
  26.     Source is formatted with a tab size of 4.
  27.  
  28.  
  29.     usage: expire [-e <days> || -<days>] [-n] [group-pattern ...]
  30.  
  31.     where <days> is number of days of articles to expire
  32.           group-pattern is an optionally wildcard group name to expire
  33.           -e gives an alternate form for specifying days to expire
  34.           -n is ignored
  35.  */
  36.  
  37. #include "defs.h"
  38. #include "expire.h"
  39. #include "amatch.h"
  40. #include <io.h>
  41. #include <ctype.h>
  42.  
  43. INFO my_stuff;
  44.  
  45. /*------------------------------- main --------------------------------*/
  46. void main(int argc, char *argv[])
  47. {
  48.     /*
  49.      *  This routine expires the news database thus:
  50.      *    - copy the index and text files into new ones, omitting the old ones
  51.      *    - update the article counters
  52.      *    - delete the old articles and rename the new files
  53.      *    - print the totals
  54.      *
  55.      *  TODO: It's too big a hunk break it up
  56.      */
  57.  
  58.     ACTIVE *gp, *head;
  59.     char   *fn, buf[256], buf2[256], subject[256];
  60.     struct stat st;
  61.     time_t current;
  62.     long   secs, i, offset;
  63.     int    days;
  64.     int    no_space = FALSE;
  65.     int    cnt;
  66.     int    matches;
  67.     long   art_time;
  68.     long   where;
  69.  
  70.     FILE   *index;
  71.     FILE   *old_index;
  72.     FILE   *text;
  73.     FILE   *old_text;
  74.  
  75.     long   articles = 0;
  76.     long   articles_deleted = 0;
  77.     long   gp_art;
  78.     long   gp_art_deleted;
  79.  
  80.     long   total_bytes = 0;
  81.     long   total_bytes_deleted = 0;
  82.     long   gp_bytes;
  83.     long   gp_bytes_deleted;
  84.  
  85.     signal(SIGINT, sig_break);        /* turn control-break off */
  86.  
  87.     fprintf(stderr, "EXPIRE: (%s)\n\n", VERSION);
  88.  
  89.     if ((argc < 2) || ((argv[1][0] == '-') &&
  90.             (!isdigit(argv[1][1]) && (argv[1][1] != 'e')))) {
  91.         fprintf(stderr, "usage: expire [-e <days> || -<days>] [-n] [group-pattern ...]\n");
  92.         exit(2);
  93.     }
  94.  
  95.     argc--;
  96.     argv++;
  97.  
  98.     time(¤t);
  99.  
  100.     /* get days to expire in -<days> format */
  101.     if ((argv[0][0] == '-') && isdigit(argv[0][1])) {
  102.         days = atoi(*argv + 1);
  103.         secs = days * 86400l;
  104.         argc--;
  105.         argv++;
  106.  
  107.     /* get days to expire in -e <days> format */
  108.     } else if ((argc >= 2) && (argv[0][0] == '-') && (argv[0][1] == 'e') &&
  109.                 isdigit(argv[1][0])) {
  110.         argc--;
  111.         argv++;
  112.         days = atoi(*argv);
  113.         secs = days * 86400l;
  114.         argc--;
  115.         argv++;
  116.  
  117.     } else {
  118.         fprintf(stderr, "usage: expire [-e <days> || -<days>] [-n] [group-pattern ...]\n");
  119.         exit(1);
  120.     }
  121.  
  122.     /* ignore -n flag */
  123.     if (argc && (argv[0][0] == '-') && (argv[0][1] == 'n')) {
  124.         argc--;
  125.         argv++;
  126.     }
  127.  
  128.     if (!load_stuff()) {
  129.         fprintf(stderr, "Couldn't read rc info\n");
  130.         exit(1);
  131.     }
  132.  
  133.     head = load_active_file();
  134.  
  135.  
  136.  
  137.     printf("%-40s :      ARTICLES         DELETED\n\n", "NEWSGROUP");
  138.  
  139.   for (gp = head; (gp != NULL) && !no_space && !break_hit; gp = gp->next) {
  140.  
  141.     gp_art = 0;
  142.     gp_art_deleted = 0;
  143.     gp_bytes = 0;
  144.     gp_bytes_deleted = 0;
  145.  
  146.     if ((gp->hi_num - gp->lo_num) > 0) {
  147.  
  148.           printf("%-40s :  ", gp->group);
  149.           fflush(stdout);
  150.  
  151.         /*
  152.          *  Open all the files.  First the old ones, then the new
  153.          */
  154.  
  155.         fn = make_news_group_name(gp->group);
  156.         stat(fn, &st);
  157.  
  158.         if (argc) {
  159.         matches = FALSE;
  160.         for (cnt = 0; cnt < argc; cnt++)
  161.           if (amatch(argv[cnt], gp->group))
  162.             matches = TRUE;
  163.         }
  164.         else
  165.           matches = TRUE;
  166.  
  167.         if (!matches) {
  168.             gp_art = gp->hi_num - gp->lo_num;
  169.             printf("%4ld %5ld k\n", gp_art, (st.st_size+500)/1000);
  170.             articles += gp_art;
  171.             total_bytes += st.st_size;
  172.             continue;
  173.         }
  174.  
  175.         gp_bytes_deleted = st.st_size;
  176.  
  177.         if ((old_text = fopen(fn, "rb")) == NULL)
  178.           crash("can't open old text", fn);
  179.         setvbuf(old_text, NULL, _IOFBF, IOBUFSIZE);
  180.         sprintf(buf, "%s.idx", fn);
  181.         if ((old_index = fopen(buf, "rb")) == NULL)
  182.           crash("can't open old index", buf);
  183.         setvbuf(old_index, NULL, _IOFBF, IOBUFSIZE);
  184.  
  185.         sprintf(buf, "%s.new", fn);
  186.         if ((text = fopen(buf, "wb")) == NULL)
  187.           crash("can't create new text", buf);
  188.         setvbuf(text, NULL, _IOFBF, IOBUFSIZE);
  189.         sprintf(buf, "%s.ndx", fn);
  190.         if ((index = fopen(buf, "wb")) == NULL)
  191.           crash("can't create new index", buf);
  192.         setvbuf(index, NULL, _IOFBF, IOBUFSIZE);
  193.  
  194.         /* numbers go chronologically -- unless an odd thing happened during
  195.            unbatch, in which case this routine can make article numbers in
  196.            the user's .nrc file not match up with actual articles */
  197.  
  198.         for (i = (gp->lo_num)+1; i <= gp->hi_num; i++) {
  199.  
  200.           fgets(buf, 255, old_index);
  201.           if (i != atol(buf+9)) {
  202.             fprintf(stderr, "\nsnews: article %ld found when %ld"
  203.                 " expected\n", atol(buf+9), i);
  204.             exit(1);
  205.           }
  206.  
  207.           /* get the time the article was processed */
  208.           art_time = atol(buf+18);
  209.           /* and the subject */
  210.           strcpy(subject, buf+28);
  211.  
  212.           if ((current - art_time) > secs) {
  213.  
  214.             /*
  215.              *  Older than req'd - just count the totals
  216.              */
  217.  
  218.             gp_art_deleted++;
  219.             gp->lo_num++;
  220.  
  221.           } else {
  222.  
  223.             /*
  224.              *  Younger than limit, so keep the article
  225.              */
  226.             where = ftell(text);
  227.  
  228.             /* copy to new file */
  229.             offset = atol(buf);
  230.             fseek(old_text, offset, SEEK_SET);
  231.  
  232.             while (fgets(buf, 255, old_text)) {
  233.  
  234.                 if (fputs(buf, text) == EOF) {
  235.                     no_space = TRUE;
  236.                     break;
  237.                 }
  238.  
  239.                 if (strnicmp(buf, "@@@@END", 7) == 0)
  240.                     break;
  241.             } /* while */
  242.  
  243.             /* save the header info */
  244.             fprintf(index,"%08ld %08ld %09ld %s", where, i,
  245.                 art_time, subject);
  246.           }
  247.  
  248.           if (no_space)
  249.             break;
  250.         } /* for */
  251.  
  252.         /*
  253.          *  Close and rename the files
  254.          */
  255.  
  256.         fclose(old_text);
  257.         fclose(old_index);
  258.         if (fclose(text))
  259.             no_space = TRUE;
  260.         if (fclose(index))
  261.             no_space = TRUE;
  262.  
  263.         if (!no_space)
  264.             update_active_entry(gp);
  265.  
  266.         /* out of disk on expire, delete the temp files */
  267.         if (no_space) {
  268.             fprintf(stderr, "expire: no room to expire %s\n", gp->group);
  269.             sprintf(buf2, "%s.NEW", fn);
  270.             unlink(buf2);
  271.             sprintf(buf2, "%s.NDX", fn);
  272.             unlink(buf2);
  273.  
  274.         } else {
  275.             unlink(fn);
  276.             sprintf(buf2, "%s.NEW", fn);
  277.             stat(buf2, &st);
  278.             gp_bytes = st.st_size;
  279.             rename(buf2, fn);
  280.  
  281.             sprintf(buf, "%s.IDX", fn);
  282.             unlink(buf);
  283.             sprintf(buf2, "%s.NDX", fn);
  284.             rename(buf2, buf);
  285.         }
  286.  
  287.         /* print all groups with articles */
  288.  
  289.         gp_art = gp->hi_num - gp->lo_num;
  290.         gp_bytes_deleted -= gp_bytes;
  291.  
  292.         articles += gp_art;
  293.         articles_deleted += gp_art_deleted;
  294.         total_bytes += gp_bytes;
  295.         total_bytes_deleted += gp_bytes_deleted;
  296.  
  297.         if ((gp_art > 0) || (gp_art_deleted > 0)) {
  298.  
  299.             if (gp_art_deleted > 0)
  300.               printf("%4ld %5ld k     %4ld %5ld k\n",
  301.                  gp_art, (gp_bytes+500)/1000,
  302.                  gp_art_deleted, (gp_bytes_deleted+500)/1000);
  303.             else
  304.               printf("%4ld %5ld k\n",
  305.                  gp_art, (gp_bytes+500)/1000);
  306.  
  307.         }
  308.     }
  309.  
  310.   } /* for */
  311.  
  312.     close_active_file();
  313.     if (!no_space)
  314.         expire_history(current, secs);
  315.  
  316.     printf("\n%7ld articles deleted\n"
  317.        "%7ld k of text deleted\n",
  318.        articles_deleted,
  319.        (total_bytes_deleted+500)/1000);
  320.     if (!no_space)
  321.         printf("%7ld articles remaining\n"
  322.            "%7ld k of text remaining\n",
  323.            articles,
  324.            (total_bytes+500)/1000);
  325.  
  326.     exit(no_space);
  327. }
  328.  
  329.  
  330. /*----------------------------------------------------------------------*/
  331. void crash(char *msg, char *fn)
  332. {
  333.     /*
  334.      *  Abort if file open error
  335.      */
  336.  
  337.     fprintf(stderr, "\nexpire: %s, %s\n", msg, fn);
  338.     exit(1);
  339. }
  340.  
  341.  
  342. /*--------------------------- expire history entries --------------------*/
  343. void expire_history(long current, long secs)
  344. {
  345.     FILE *hist_file, *new_hist_file;
  346.     long age;
  347.     char buf[512], buf2[256];
  348.  
  349.  
  350.     /* open the files */
  351.     sprintf(buf, "%shistory", my_stuff.news_dir);
  352.     if ((hist_file = fopen(buf, "rb")) == NULL) {
  353.         fprintf(stderr, "expire: cannot open file %s for input\n", buf);
  354.         exit(1);
  355.     }
  356.     setvbuf(hist_file, NULL, _IOFBF, IOBUFSIZE);
  357.     sprintf(buf, "%shistory.new", my_stuff.news_dir);
  358.     if ((new_hist_file = fopen(buf, "wb")) == NULL) {
  359.         fprintf(stderr, "expire: cannot open file %s for output\n", buf);
  360.         exit(1);
  361.     }
  362.     setvbuf(new_hist_file, NULL, _IOFBF, IOBUFSIZE);
  363.  
  364.     while (fgets(buf, 255, hist_file) != NULL) {
  365.         sscanf(buf, "%*s %ld", &age);
  366.         if ((current-age) < secs) {
  367.             fputs(buf, new_hist_file);
  368.         }
  369.     }
  370.  
  371.     fclose(hist_file);
  372.     fclose(new_hist_file);
  373.  
  374.     sprintf(buf, "%shistory.bak", my_stuff.news_dir);
  375.     unlink(buf);
  376.     sprintf(buf2, "%shistory", my_stuff.news_dir);
  377.     rename(buf2, buf);
  378.     sprintf(buf, "%shistory.new", my_stuff.news_dir);
  379.     rename(buf, buf2);
  380.     sprintf(buf, "%shistory.bak", my_stuff.news_dir);
  381.     unlink(buf);
  382. }
  383.