home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 408_01 / unbatch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-13  |  15.1 KB  |  540 lines

  1. /*
  2.     SNEWS 1.91
  3.  
  4.     unbatch - quick and dirty news toss, no feeding of other sites
  5.  
  6.  
  7.     Copyright (C) 1991  John McCombs, Christchurch, NEW ZEALAND
  8.                         john@ahuriri.gen.nz
  9.                         PO Box 2708, Christchurch, NEW ZEALAND
  10.  
  11.     Modifications copyright (C) 1993  Daniel Fandrich
  12.                         <dan@fch.wimsey.bc.ca> or CompuServe 72365,306
  13.  
  14.     This program is free software; you can redistribute it and/or modify
  15.     it under the terms of the GNU General Public License, version 1, as
  16.     published by the Free Software Foundation.
  17.  
  18.     This program is distributed in the hope that it will be useful,
  19.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.     GNU General Public License for more details.
  22.  
  23.     See the file COPYING, which contains a copy of the GNU General
  24.     Public License.
  25.  
  26.  
  27.     Source is formatted with a tab size of 4.
  28.  
  29.  
  30.     USAGE: unbatch
  31.         -n    means decompress the first batch, then stop before tossing
  32.         -v    means verbose, tell what we are doing   NOT IMPLEMENTED
  33.         -x n  debug level -- higher numbers give more info
  34.  
  35.  */
  36.  
  37.  
  38. #include "defs.h"
  39. #include "unbatch.h"
  40. #include <process.h>
  41. #include <ctype.h>
  42.  
  43. #define BUFFSIZE 16000
  44. #define BATCH_HEADER "#! cunbatch\n"
  45. #define NO_SUBJECT "-- no subject --\n"  /*"<none>\n"*/
  46.  
  47. unsigned _stklen = 16384;
  48. char *inbuf  = NULL;
  49. char *outbuf = NULL;
  50. int debug = 0;
  51.  
  52. INFO my_stuff;
  53.  
  54.  
  55. /*------------------------------- main --------------------------------*/
  56. int main(int argc, char *argv[])
  57. {
  58.     FILE   *tmp_file;
  59.     static char name[256], in_name[256];
  60.     int    done, no_toss;
  61. /*    int    drive;
  62.     long   required_disk, disk_free;
  63.     struct stat st;
  64.     struct dfree df;
  65. */
  66.     struct ffblk ffblk;
  67.  
  68.     signal(SIGINT, sig_break);        /* turn control-break off */
  69.  
  70.     fprintf(stderr, "UNBATCH: (%s)\n\n", VERSION);
  71.  
  72.     /* if TRUE, then just uncompress, don't unbatch */
  73.  
  74.     /*
  75.     inbuf  = malloc(BUFFSIZE);
  76.     outbuf = malloc(BUFFSIZE);
  77.  
  78.     if (!inbuf || !outbuf) {
  79.         fprintf(stderr, "unbatch: not enough memory to set file buffers");
  80.         exit(1);
  81.     } */
  82.  
  83.     if ((argc > 1) && ((argv[1][0] == '-') || (argv[1][0] == '/')) &&
  84.         ((argv[1][1] == '?') || (argv[1][1] == 'h'))) {
  85.             printf("Usage: unbatch [-n] [-x debug]\n");
  86.         exit(2);
  87.     }
  88.  
  89.     no_toss = (argc >= 2) && (strncmp("-n", argv[1], 2) == 0);
  90.     if ((argc >= 3+no_toss) && (strcmp("-x", argv[1+no_toss]) == 0))
  91.         debug = atoi(argv[2+no_toss]);    /* set debug level */
  92.  
  93.     if (debug >= 1)
  94.         printf("loading config... ");
  95.     if (!load_stuff()) {
  96.         fprintf(stderr, "unbatch: can't read rc info\n");
  97.         exit(1);
  98.     }
  99.     if (debug >= 1)
  100.         printf("loading active... ");
  101.     load_active_file();
  102.     if (debug >= 1)
  103.         printf("loading history... ");
  104.     load_history_list();
  105.     if (debug >= 1)
  106.         printf("\n\n");
  107.  
  108.     sprintf(in_name, "%s*.*", my_stuff.incoming_dir);
  109.     done = findfirst(in_name, &ffblk, 0);
  110.     while (!done && !break_hit) {
  111.  
  112.         sprintf(name, "%s%s", my_stuff.incoming_dir, ffblk.ff_name);
  113.         printf("unbatch: processing %s\n", name);
  114.  
  115.         /*
  116.          *  Check for enough room.  We need:
  117.          *
  118.          *     - more than twice the size of the batch for uncompressed
  119.          *       batch, say 2.8
  120.          *
  121.          *     - space for the articles.
  122.          *
  123.          *       For example a 100k batch may require 280kb for the uncompressed
  124.          *       batch, then another 280 kb for the articles.
  125.          */
  126. /*
  127.         stat(name, &st);
  128.  
  129.         required_disk = (st.st_size*2.8) * 2;
  130.  
  131.         drive = getdisk();
  132.         getdfree(drive+1, &df);
  133.         disk_free = (long)df.df_avail * (long)df.df_bsec * (long)df.df_sclus;
  134.  
  135.         if (disk_free < required_disk){
  136.             fprintf(stderr, "unbatch: %ld bytes of disk req'd to unpack batch\n");
  137.             exit(1);
  138.         }
  139. */
  140.  
  141.         /* uncompress the news batch and return a pointer to the temp file */
  142.         if ((tmp_file = decode_batches(name, no_toss)) != NULL) {
  143.  
  144.             open_hist_file();
  145.             toss(tmp_file);
  146.             close_hist_file();
  147.             fclose(tmp_file);
  148.  
  149.             unlink(name);        /* kill the batch */
  150.             sprintf(name, "%s", my_stuff.temp_name);
  151.             unlink(name);
  152.  
  153.         } else {
  154.             fprintf(stderr, "unbatch: could not unpack compressed news batch %s\n", name);
  155.             exit(1);
  156.         }
  157.  
  158.         done = findnext(&ffblk);
  159.  
  160.     } /* while */
  161.  
  162.     close_active_file();
  163.     if (break_hit) {
  164.         fprintf(stderr, "unbatch: aborting due to ctrl-break\n");
  165.         return 2;
  166.     }
  167.  
  168.     return 0;
  169. }
  170.  
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177. /*--------------------------- unpack the batch ------------------------*/
  178. void toss(FILE *tmp_file)
  179. {
  180.     /*
  181.      *  Toss it into the appropriate files.
  182.      *
  183.      *  TODO:
  184.      *    - badly structured, sort it out
  185.      */
  186.  
  187.     /* make these static to avoid chewing up large amounts of stack */
  188.     static char buf[1024], msg[256], subject[256], msg_id[256];
  189.     static char newsgroups[1024], nglist[1024];
  190.  
  191.     FILE *out_file = NULL;
  192.     FILE *spool_file = NULL;
  193.     char *p;
  194.     char junk_group[] = "junk";
  195.     char tempname[81];
  196.     long where;
  197.     ACTIVE *gp;
  198.     time_t t;
  199.     int  /*already_junked,*/ in_header, posted;
  200.  
  201.     strcpy(msg_id, "");
  202.     strcpy(subject, NO_SUBJECT);
  203.     strcpy(newsgroups, "");
  204.  
  205.     rewind(tmp_file);
  206.     sprintf(tempname, "%sitem%04x.tmp", my_stuff.temp_str, getpid());
  207.     time(&t);
  208.     in_header = TRUE;
  209.  
  210.     /* read the file */
  211.     while (fgets(buf, 511, tmp_file) != NULL) {
  212.  
  213.         if ((strncmp(buf, "#! rnews ", 9) == 0) && isdigit(buf[9])) {
  214.  
  215.             if (strlen(newsgroups) != 0) {        /* we've read in an article */
  216.               if (debug >= 2)
  217.                     printf("----- new article %s\n", msg_id);
  218.  
  219.               if (find_msg_id(msg_id) != NULL) {
  220.                     if (debug >= 1)
  221.                         printf("discarding duplicate article %s\n", msg_id);
  222.               } else {
  223.  
  224.                 posted = 0;
  225.                 strcpy(nglist, newsgroups+11);
  226.                 strtok(newsgroups, " \r\n,:");
  227.                 p = strtok(NULL, " \r\n,:");
  228.  
  229.                 /*
  230.                  *  For each newsgroup
  231.                  *    - open the text file
  232.                  *    - save the file pointer
  233.                  *    - append the message to it
  234.                  *    - close the file
  235.                  *    - open the index file
  236.                  *    - save the file pointer and the subject line
  237.                  */
  238.  
  239.                 while (p != NULL) {        /* post to each group in Newsgroups: */
  240.  
  241.                     if (strcmp(find_news_group(p)->group, junk_group) != 0) {
  242.                         out_file = open_out_file(p);
  243.                         if (debug >= 2)
  244.                             printf("storing article in %s\n", p);
  245.                         posted = 1;
  246.                         where = ftell(out_file);
  247.                         rewind(spool_file);
  248.                         while (fgets(buf, 511, spool_file) != NULL)
  249.                             fputs(buf, out_file);
  250.                         fprintf(out_file, "\n@@@@END\n");
  251.                         if (fclose(out_file)) {
  252.                             fprintf(stderr, "unbatch: can't write article file\n");
  253.                             exit(1);
  254.                         }
  255.  
  256.                         out_file = open_index_file(p);
  257.                         gp = find_news_group(p);
  258.                         fprintf(out_file,"%08ld %08ld %09ld %s", where,
  259.                             gp->hi_num, t, subject);
  260.                         if (fclose(out_file)) {
  261.                             fprintf(stderr, "unbatch: can't write index file\n");
  262.                             exit(1);
  263.                         }
  264.                     } else
  265.                         if (debug >= 2)
  266.                             printf("group %s doesn't exist\n", p);
  267.                     p = strtok(NULL, " \r\n,:");
  268.                 } /* while */
  269.  
  270.                 if (!posted) {
  271.                     if (debug >= 1)
  272.                         printf("junking article %s\n", msg_id);
  273.                     out_file = open_out_file(junk_group);
  274.                     if (out_file) {
  275.                         where = ftell(out_file);
  276.                         rewind(spool_file);
  277.                         while (fgets(buf, 511, spool_file) != NULL)
  278.                             fputs(buf, out_file);
  279.                         fprintf(out_file, "\n@@@@END\n");
  280.                         if (fclose(out_file)) {
  281.                             fprintf(stderr, "unbatch: can't write article file\n");
  282.                             exit(1);
  283.                         }
  284.  
  285.                         out_file = open_index_file(junk_group);
  286.                         gp = find_news_group(junk_group);
  287.                         fprintf(out_file,"%08ld %08ld %09ld %s", where,
  288.                             gp->hi_num, t, subject);
  289.                         if (fclose(out_file)) {
  290.                             fprintf(stderr, "unbatch: can't write index file\n");
  291.                             exit(1);
  292.                         }
  293.                     }
  294.                     else {
  295. /* will never get to this point because open_out_file() aborts if no junk */
  296.                         fprintf(stderr,"\nunbatch: junk group *must* exist!");
  297.                         exit(1);
  298.                     }
  299.                 } /* if */
  300.                 add_hist_record(msg_id, nglist);
  301.  
  302.               } /* if */
  303.               if (fclose(spool_file)) {
  304.                 fprintf(stderr, "unbatch: can't write spool file\n");
  305.                 exit(1);
  306.               }
  307.             } /* if */
  308.  
  309.             strcpy(subject, NO_SUBJECT);
  310.             in_header = TRUE;
  311.  
  312.             if ((spool_file = fopen(tempname, "w+b")) == NULL) {
  313.                 fprintf(stderr, "unbatch: can't open temp article file %s\n", tempname);
  314.                 exit(1);
  315.             }
  316.  
  317.  
  318.         } else {                        /* parse article text */
  319.             /* flag the end of the header */
  320.             if (strcmp(buf, "\n") == 0)
  321.                 in_header = FALSE;
  322.  
  323.             /* save the newsgroups line */
  324.             if (in_header) {
  325.                 if (strnicmp(buf,"Message-ID:",11) == 0) {
  326.                     strncpy(msg, buf, sizeof(msg));
  327.                     msg[sizeof(msg)-1] = '\x0';
  328.                     strtok(msg, " \t\r\n");
  329.                     p = strtok(NULL, " \t\r\n");
  330.                     if (p)        /* else we should really kill the article */
  331.                         strcpy(msg_id, p);
  332.                 }
  333.                 if (strnicmp(buf,"Newsgroups:",11) == 0)
  334.                     strcpy(newsgroups, buf);
  335.                 if (strnicmp(buf,"Subject:",8) == 0) {
  336.                     strncpy(subject, buf+8, sizeof(subject));
  337.                     subject[sizeof(subject)-1] = '\x0';
  338.                 }
  339.  
  340.             /* add our system name to the path list */
  341.                 if (strnicmp(buf, "Path:", 5) == 0) {
  342.                     strtok(buf, " \t");
  343.                     p = strtok(NULL, " \t");
  344.                     fprintf(spool_file, "Path: %s!%s", my_stuff.my_site, p);
  345.                 } else
  346.                     fprintf(spool_file, "%s", buf);
  347.  
  348.             } else {                    /* body of article */
  349.                 fprintf(spool_file, "%s", buf);
  350.             } /* if */
  351.         } /* if */
  352.  
  353.     } /* while */
  354.  
  355.  
  356.  
  357.  
  358.  
  359.     /* process the last one */
  360.     if (strlen(newsgroups) != 0) {
  361.       if (debug >= 2)
  362.             printf("----- new article %s\n", msg_id);
  363.  
  364.       if (find_msg_id(msg_id) != NULL) {
  365.             if (debug >= 1)
  366.                 printf("discarding duplicate article %s\n", msg_id);
  367.       } else {
  368.  
  369.         posted = 0;
  370.         strcpy(nglist, newsgroups+11);
  371.         strtok(newsgroups, " \r\n,:");
  372.         p = strtok(NULL, " \r\n,:");
  373.  
  374.  
  375.         /* same loop here as before */
  376.  
  377.         while (p != NULL) {
  378.             if (strcmp(find_news_group(p)->group, junk_group) != 0) {
  379.                 out_file = open_out_file(p);
  380.                 if (debug >= 2)
  381.                     printf("storing article in %s\n", p);
  382.                 posted = 1;
  383.                 where = ftell(out_file);
  384.                 rewind(spool_file);
  385.                 while (fgets(buf, 511, spool_file) != NULL)
  386.                     fputs(buf, out_file);
  387.                 fprintf(out_file, "\n@@@@END\n");
  388.                 if (fclose(out_file)) {
  389.                     fprintf(stderr, "unbatch: can't write article file\n");
  390.                     exit(1);
  391.                 }
  392.  
  393.                 out_file = open_index_file(p);
  394.                 gp = find_news_group(p);
  395.                 fprintf(out_file,"%08ld %08ld %09ld %s", where, gp->hi_num, t, subject);
  396.                 if (fclose(out_file)) {
  397.                     fprintf(stderr, "unbatch: can't write index file\n");
  398.                     exit(1);
  399.                 }
  400.             } else
  401.                 if (debug >= 2)
  402.                     printf("group %s doesn't exist\n", p);
  403.             p = strtok(NULL, " \r\n,:");
  404.         } /* while */
  405.  
  406.         if (!posted) {
  407.             if (debug >= 1)
  408.                 printf("junking article %s\n", msg_id);
  409.             out_file = open_out_file(junk_group);
  410.             if (out_file) {
  411.                 where = ftell(out_file);
  412.                 rewind(spool_file);
  413.                 while (fgets(buf, 511, spool_file) != NULL)
  414.                     fputs(buf, out_file);
  415.                 fprintf(out_file, "\n@@@@END\n");
  416.                 if (fclose(out_file)) {
  417.                     fprintf(stderr, "unbatch: can't write article file\n");
  418.                     exit(1);
  419.                 }
  420.  
  421.                 out_file = open_index_file(junk_group);
  422.                 gp = find_news_group(junk_group);
  423.                 fprintf(out_file, "%08ld %08ld %09ld %s", where, gp->hi_num, t, subject);
  424.                 if (fclose(out_file)) {
  425.                     fprintf(stderr, "unbatch: can't write index file\n");
  426.                     exit(1);
  427.                 }
  428.             }
  429.         }
  430.         add_hist_record(msg_id, nglist);
  431.  
  432.       }
  433.       if (fclose(spool_file)) {
  434.         fprintf(stderr, "unbatch: can't write spool file\n");
  435.         exit(1);
  436.       }
  437.  
  438.       unlink(tempname);
  439.     } /* if */
  440. }
  441.  
  442.  
  443.  
  444.  
  445.  
  446. /*--------------------------- unpack the batch ------------------------*/
  447. FILE *decode_batches(char *fn, int no_toss)
  448. {
  449.     /*
  450.      *  take the batch, strip off the #! cunbatch, and feed the file to
  451.      *  uncompress, the opened uncompressed file is returned
  452.      */
  453.  
  454.     FILE *in_file, *out_file;
  455.     int res, buf_cnt, write_err = 0;
  456.     char buf[1025];
  457.     char name[128];
  458.     char cname[128];
  459.  
  460.     buf_cnt = 0;
  461.  
  462.     /* open the batch file */
  463.     strcpy(name, fn);
  464.     if ((in_file = fopen(name, "rb")) == NULL) {
  465.         fprintf(stderr, "unbatch: batchfile %s could not be opened\n", name);
  466.         return(NULL);
  467.     }
  468.  
  469.     /* check if it's compressed */
  470.     res = fread(buf, 1, sizeof(BATCH_HEADER)-1, in_file);
  471.     rewind(in_file);
  472.     if (strncmp(buf, BATCH_HEADER, sizeof(BATCH_HEADER)-1) != 0) {
  473.  
  474.     /* batch is already uncompressed -- copy to temp file */
  475.         if (debug >= 1)
  476.             printf("unbatch: copying uncompressed batch (%s)\n", name);
  477.         sprintf(name, "%s", my_stuff.temp_name);
  478.         if ((out_file = fopen(name, "wb")) == NULL) {
  479.             fprintf(stderr, "unbatch: cannot open output file %s\n", name);
  480.             return(NULL);
  481.         }
  482.  
  483.         while ((res = fread(buf, 1, 1024, in_file)) > 0) {
  484.             if (fwrite(buf, 1, res, out_file) != res) {
  485.                 ++write_err;
  486.                 break;
  487.             }
  488.         }
  489.         fclose(in_file);
  490.         if (fclose(out_file) || write_err) {
  491.             fprintf(stderr, "unbatch: can't copy batch (disk full?)\n");
  492.             return(NULL);
  493.         }
  494.  
  495.     } else {
  496.  
  497.     /* open the compressed */
  498.         sprintf(name, "%s.z", my_stuff.temp_name);
  499.         if ((out_file = fopen(name, "wb")) == NULL) {
  500.             fprintf(stderr, "unbatch: cannot open output file %s\n", name);
  501.             return(NULL);
  502.         }
  503.  
  504.         while ((res = fread(buf, 1, 1024, in_file)) > 0) {
  505.             if (fwrite(buf_cnt == 0 ? buf+12 : buf, 1,
  506.                         buf_cnt == 0 ? res-12 : res, out_file) != (buf_cnt == 0 ? res-12 : res)) {
  507.                 ++write_err;
  508.                 break;
  509.             }
  510.             buf_cnt++;
  511.         }
  512.  
  513.         fclose(in_file);
  514.         if (fclose(out_file) || write_err) {
  515.             fprintf(stderr, "unbatch: can't copy batch (disk full?)\n");
  516.             return(NULL);
  517.         }
  518.  
  519.         unlink(my_stuff.temp_name);
  520.         strcat(strcpy(cname, my_stuff.temp_name), ".z");
  521.         sprintf(name, my_stuff.uncompress, cname);
  522.         if (debug >= 1)
  523.             printf("unbatch: decompressing batch (%s)\n", name);
  524.         system(name);
  525.         unlink(cname);
  526.     }
  527.  
  528.     if (no_toss) return(NULL);
  529.  
  530.     /* open the uncompressed */
  531.     sprintf(name, "%s", my_stuff.temp_name);
  532.     if ((out_file = fopen(name, "rb")) == NULL) {
  533.         fprintf(stderr, "unbatch: can't open uncompressed file %s\n", name);
  534.         return(NULL);
  535.     }
  536.  
  537.     return(out_file);
  538.  
  539. }
  540.