home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / snews-20.zip / RNEWS.C < prev    next >
C/C++ Source or Header  |  1992-08-02  |  10KB  |  427 lines

  1. /*
  2.     SNEWS 2.0
  3.  
  4.     rnews - 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.     This program is free software; you can redistribute it and/or modify
  12.     it under the terms of the GNU General Public License, version 1, as
  13.     published by the Free Software Foundation.
  14.  
  15.     This program is distributed in the hope that it will be useful,
  16.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.     GNU General Public License for more details.
  19.  
  20.     See the file COPYING, which contains a copy of the GNU General
  21.     Public License.
  22.  
  23.     Derived from unbatch.c by Kai Uwe Rommel
  24.  
  25.  
  26.     USAGE: rnews
  27.             -x<debug>  when debug>9 means verbose, tell what we are doing
  28.  
  29.  */
  30.  
  31.  
  32. #include "defs.h"
  33. #include "rnews.h"
  34.  
  35. unsigned _stklen = 16384;
  36.  
  37. INFO my_stuff;
  38. char iobuf[IOBUFSIZE];
  39. int verbose, slave;
  40. int pidc, pidr;
  41.  
  42. extern char _far *_pgmptr;
  43.  
  44.  
  45. /*------------------------------- main --------------------------------*/
  46. void main(int argc, char *argv[])
  47. {
  48.     int arg;
  49.     FILE *tmp_file;
  50.  
  51.     slave = (strcmp(argv[0], "slave") == 0);
  52.  
  53.     if (argc > 1 && strncmp(argv[1], "-x", 2) == 0) {
  54.     verbose = (atoi(argv[1] + 2) >= 9);
  55.     argc--;
  56.     argv++;
  57.     }
  58.  
  59.     if (verbose && !slave)
  60.         fprintf(stderr, "RNEWS: (%s)\n", VERSION);
  61.  
  62.     if (!load_stuff()) {
  63.         fprintf(stderr, "Couldn't read rc info\n");
  64.         exit(1);
  65.     }
  66.  
  67.     load_active_file();
  68.     open_hist_file();
  69.     free_ng();
  70.  
  71.     if (argc == 1) {
  72.  
  73.     if (isatty(0)) {
  74.         if (!verbose)
  75.             fprintf(stderr, "RNEWS: (%s)\n", VERSION);
  76.         fprintf(stderr, "\nusage: rnews [-v] [file ...]\n");
  77.         exit(1);
  78.     }
  79.      
  80.     setmode(fileno(stdin), O_BINARY);
  81.     tmp_file = fdopen(dup(fileno(stdin)), "rb");
  82.     decode_batch(tmp_file, "<stdin>");
  83.  
  84.     }
  85.     else
  86.       for (arg = 1; arg < argc; arg++)
  87.       if ((tmp_file = fopen(argv[arg], "rb")) != NULL) {
  88.           decode_batch(tmp_file, argv[arg]);
  89.           fclose(tmp_file);
  90.       }
  91.  
  92.     close_hist_file();
  93.     close_active_file();
  94.  
  95.     exit(0);
  96. }
  97.  
  98.  
  99. /*--------------------------- unpack the batch ------------------------*/
  100. void write_logentry(char *line)
  101. {
  102.   static FILE *logfile;
  103.   char buf[256];
  104.  
  105.   if (logfile == NULL) {
  106.     strcpy(buf, my_stuff.spool_dir);
  107.     strcat(buf, "rnews.log");
  108.     logfile = fopen(buf, "a");
  109.   }
  110.  
  111.   if (logfile) {
  112.     _strdate(buf);
  113.     buf[5] = '-';
  114.     _strtime(buf + 6);
  115.     buf[11] = 0;
  116.     fprintf(logfile, "%s %s\n", buf, line);
  117.   }
  118. }
  119.  
  120. long save_message(LINE *spool, char *newsgroups, 
  121.           char *subject, char *msg_id)
  122. {
  123.     /*
  124.      *  For each newsgroup
  125.      *    - open the text file
  126.      *    - save the file pointer
  127.      *    - append the message to it
  128.      *    - close the file
  129.      *    - open the index file
  130.      *    - save the file pointer and the subject line
  131.      */
  132.     char buf[512], nglist[256], log[1024], *group, *p;
  133.     FILE *out_file = NULL;
  134.     LINE *help;
  135.     ACTIVE *gp;
  136.     long where;
  137.     time_t t;
  138.     int saved = FALSE;
  139.     long lines = 0, bytes = 0, cross = 0;
  140.  
  141.     for (help = spool; help; help = help->next) {
  142.     lines++;
  143.     bytes += strlen(help->data);
  144.     }
  145.  
  146.     for (p = subject; *p && isspace(*p); p++);
  147.     strcpy(buf, "(");
  148.     strcat(buf, p);
  149.     if (buf[strlen(buf) - 1] == '\n')
  150.         buf[strlen(buf) - 1] = 0;
  151.     buf[19] = 0;
  152.     strcat(buf,")");
  153.  
  154.     if (verbose)
  155.         sprintf(log, "%4ld %6ld %-20.20s to:", lines, bytes, buf);
  156.  
  157.     time(&t);
  158.     nglist[0] = 0;
  159.  
  160.     p = strtok(newsgroups, " \r\n,:");
  161.     p = strtok(NULL, " \r\n,:");
  162.  
  163.     while (p != NULL) {
  164.  
  165.     group = p;
  166.     p = strtok(NULL, " \r\n,:");
  167.  
  168.     gp = find_news_group(group);
  169.     if (stricmp(gp->group, "junk") == 0 && (p != NULL || saved))
  170.       continue;
  171.  
  172.     if (verbose) {
  173.       strcat(log, " ");
  174.           strcat(log, gp->group);
  175.         }
  176.  
  177.     out_file = open_out_file(group);
  178.     where = ftell(out_file);
  179.     help = spool;
  180.  
  181.     setvbuf(out_file, iobuf, _IOFBF, IOBUFSIZE);
  182.  
  183.     for (help = spool; help != NULL; help = help->next)
  184.         fputs(help->data, out_file);
  185.  
  186.     fprintf(out_file, "\n@@@@END\n");
  187.     fclose(out_file);
  188.   
  189.     out_file = open_index_file(group);
  190.     fprintf(out_file,"%08ld %08ld %09ld %s", where,
  191.         gp->hi_num, t, subject);
  192.     fclose(out_file);
  193.  
  194.     if (saved)
  195.       cross++;
  196.     else
  197.       saved = TRUE;
  198.       
  199.         if ( nglist[0] )
  200.           strcat(nglist, ",");
  201.         strcat(nglist, group);
  202.     }
  203.  
  204.     if (verbose) {
  205.         write_logentry(log);
  206.         fprintf(stderr, "%s\n", log);
  207.     }
  208.  
  209.     while (spool) {
  210.         help = spool;
  211.     spool = spool->next;
  212.     free(help->data);
  213.     free(help);
  214.     }
  215.  
  216.     add_hist_record(msg_id, nglist);
  217.     return cross;
  218. }
  219.  
  220. void toss(FILE *tmp_file)
  221. {
  222.     /*
  223.      *  Toss it into the appropriate files.
  224.      */
  225.     LINE *spool = NULL, *help;
  226.     char buf[512], buf2[512], *p;
  227.     char newsgroups[256], subject[256], msg_id[256];
  228.     int  in_header, control;
  229.     long lines = 0, articles = 0, cross = 0, bytes = 0;
  230.  
  231.     strcpy(msg_id, "");
  232.     strcpy(subject, "-- no subject --\n");
  233.     strcpy(newsgroups, "");
  234.  
  235.     in_header = TRUE;
  236.     control = FALSE;
  237.  
  238.     /* read the file */
  239.     while (fgets(buf, 511, tmp_file) != NULL) {
  240.  
  241.         if (strstr(buf, "#! rnews") != NULL) {
  242.  
  243.             if (control)
  244.                 strcpy(newsgroups, "Newsgroups: control"); /* kludge */
  245.  
  246.         if (spool != NULL) {
  247.             cross += save_message(spool, newsgroups, subject, msg_id);
  248.             articles++;
  249.         }
  250.  
  251.             strcpy(subject, "-- no subject --\n");
  252.             in_header = TRUE;
  253.             control = FALSE;
  254.         spool = NULL;
  255.  
  256.         } else {
  257.             /* flag the end of the header */
  258.             if (strcmp(buf, "\n") == 0)
  259.                 in_header = FALSE;
  260.  
  261.             /* save the newsgroups line */
  262.             if (in_header) {
  263.                 if (strnicmp(buf,"Message-ID:",11) == 0) {
  264.                     strcpy(buf2, buf);
  265.                     p = strtok(buf2, " \t\r\n");  p = strtok(NULL, " \t\r\n");
  266.                     strcpy(msg_id, p);
  267.                 }
  268.                 if (strnicmp(buf,"Newsgroups:",11) == 0)
  269.                     strcpy(newsgroups,buf);
  270.                 if (strnicmp(buf,"Subject:",8) == 0)
  271.                     strcpy(subject, buf+8);
  272.                 if (strnicmp(buf,"Control:",8) == 0)
  273.                     control = TRUE;
  274.                 /* add our system name to the path list */
  275.                 if (strnicmp(buf, "Path:", 5) == 0) {
  276.                     p = strtok(buf, " \t");
  277.                     p = strtok(NULL, " \t");
  278.             strcpy(buf2, p);
  279.                     sprintf(buf, "Path: %s!%s", my_stuff.my_site, buf2);
  280.                 }
  281.             }
  282.  
  283.         if (spool == NULL)
  284.         spool = help = (LINE *) xmalloc(sizeof(LINE));
  285.         else {
  286.             help->next = (LINE *) xmalloc(sizeof(LINE));
  287.         help = help->next;
  288.         }
  289.         help->next = NULL;
  290.         help->data = (char *) xmalloc(strlen(buf) + 1);
  291.         strcpy(help->data, buf);
  292.  
  293.         lines++;
  294.         bytes += strlen(buf);
  295.         }
  296.  
  297.     }
  298.  
  299.     /* process the last one */
  300.  
  301.     if (control)
  302.         strcpy(newsgroups, "Newsgroups: control"); /* kludge */
  303.  
  304.     if (spool != NULL) {
  305.     cross += save_message(spool, newsgroups, subject, msg_id);
  306.         articles++;
  307.     }
  308.  
  309.     sprintf(buf, 
  310.         "Delivered %ld articles, %ld crossposts, %ld lines, %ldk bytes.",
  311.             articles, cross, lines, (bytes + 512) / 1024);
  312.     write_logentry(buf);
  313.     fprintf(stderr, "rnews: %s\n", buf);
  314. }
  315.  
  316.  
  317. /*--------------------------- unpack the batch ------------------------*/
  318. FILE *create_pipe(char *compressor)
  319. {
  320.     int pipe1[2], pipe2[2], oldout;
  321.     
  322.     _pipe(pipe1, 4096, O_BINARY);
  323.     _pipe(pipe2, 4096, O_BINARY);
  324.     noinherit(pipe1[1]);
  325.     noinherit(pipe2[0]);
  326.  
  327.     oldout = dup(1);
  328.  
  329.     close(0);
  330.     dup2(pipe1[0], 0);
  331.     close(pipe1[0]);
  332.     close(1);
  333.     dup2(pipe2[1], 1);
  334.     close(pipe2[1]);
  335.  
  336.     pidc = spawnlp(P_NOWAIT, compressor, compressor, "-d", NULL);
  337.  
  338.     close(0);
  339.     dup2(pipe2[0], 0);
  340.     close(pipe2[0]);
  341.     close(1);
  342.     dup2(oldout, 1);
  343.     close(oldout);
  344.  
  345.     pidr = spawnlp(P_NOWAIT, _pgmptr, "slave", verbose ? "-x9" : NULL, NULL);
  346.  
  347.     close(0);
  348.  
  349.     return fdopen(pipe1[1], "wb");
  350. }
  351.  
  352. void close_pipe(FILE *stream)
  353. {
  354.     fclose(stream);
  355.  
  356.     cwait(NULL, pidc, WAIT_CHILD);
  357.     cwait(NULL, pidr, WAIT_CHILD);
  358. }
  359.  
  360. void decode_batch(FILE *in_file, char *fn)
  361. {
  362.     /*
  363.      *  take the batch, strip off the !cunbatch, and feed the file to
  364.      *  uncompress, the opened uncompressed file is returned
  365.      */
  366.  
  367.     FILE *out_file;
  368.     int res, header;
  369.     char buf[1024], *compressor;
  370.     long pos;
  371.     short magic;
  372.  
  373.     if (fgets(buf, sizeof(buf), in_file) == NULL) {
  374.         fprintf(stderr, "batch %s is inexplicably too small\n", fn);
  375.         return;
  376.     }
  377.  
  378.     if (memcmp(buf, "#! rnews ", 9) == 0) {
  379.     if (verbose)
  380.         fprintf(stderr, "Unpacking %s ...\n", fn);
  381.         toss(in_file);
  382.     return;
  383.     }
  384.  
  385.     if (memcmp(buf, "#! cunbatch\n", 12) == 0)
  386.         header = TRUE;
  387.     else if (memcmp(buf, "#! funbatch\n", 12) == 0)
  388.         header = TRUE;
  389.     else
  390.         header = FALSE;
  391.  
  392.     if (header)
  393.       fread(&magic, 1, sizeof(short), in_file);
  394.     else
  395.       memcpy(&magic, buf, sizeof(short));
  396.  
  397.     if (magic == COMPRESS)
  398.         compressor = "compress";
  399.     else if (magic == FREEZE)
  400.         compressor = "freeze";
  401.     else {
  402.         fprintf(stderr, "batch %s has unknown compression type\n", fn);
  403.     return;
  404.     }
  405.  
  406.     out_file = create_pipe(compressor);
  407.  
  408.     if (out_file == NULL) {
  409.     fprintf(stderr, "Cannot create pipe for %s.\n", fn);
  410.     return;
  411.     }
  412.  
  413.     if (verbose)
  414.       fprintf(stderr,"Piping compressed %s to '%s -d' and slave 'rnews' ...\n",
  415.               fn, compressor);
  416.  
  417.     if (header)
  418.       fwrite(&magic, 1, sizeof(short), out_file);
  419.     else
  420.       fputs(buf, out_file);
  421.  
  422.     while ((res = fread(buf, 1, 1024, in_file)) > 0)
  423.     fwrite(buf, 1, res, out_file);
  424.  
  425.     close_pipe(out_file);
  426. }
  427.