home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / TELECOM / UUCPbb_2_1_src.lzh / UUCPBB21 / rnews.c < prev    next >
C/C++ Source or Header  |  1994-09-25  |  9KB  |  341 lines

  1. /*  rnews.c  --This is the main program to process and distribute Usenet news.
  2.     Copyright (C) 1994 Brad Spencer
  3.  
  4.     This file is part of the OS-9 UUCP package, UUCPbb.
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20.     The author of UUCPbb, Bob Billson, can be contacted at:
  21.     bob@kc2wz.bubble.org  or  uunet!kc2wz!bob  or  by snail mail:
  22.     21 Bates Way, Westfield, NJ 07090
  23. */
  24.  
  25. /* main function */
  26.  
  27. #define MAIN
  28. #include "uucp.h"
  29. #include "rnews.h"
  30. #include "mbuf.h"
  31. #include "getopt.h"
  32. #include <direct.h>
  33.  
  34. QQ int debuglvl = 0;
  35. struct mbuf *getgroups();
  36.  
  37. main(argc,argv)
  38. int argc;
  39. char *argv[];
  40. {
  41.      char lbuf[512], buf[BIGBUF], filename[100], initng[100];
  42.      struct fildes fdes;
  43.      FILE *batchfile;
  44.      int savein, saveout, fd, pipefd;
  45.      char *bigbuf;
  46.      int e,p,option,zflag=0;
  47.      struct mbuf *g,*gg;
  48.      long length = -1;
  49.  
  50.      initng[0] = '\0';
  51.  
  52. #ifndef _OSK
  53.      pflinit();
  54. #endif
  55.  
  56.      /* On the CC3 there seems to be a bit of arcane lore that is needed to
  57.         make setbuf() work without crashing on exit.  This malloc is part of
  58.         what I discovered to work.  */
  59.  
  60.      if ((bigbuf = (char *) malloc (BUFSIZ+16)) == NULL)
  61.        {
  62.           fprintf (stderr, "Can't allocate file buffer\n");
  63.           exit(207);
  64.        }
  65.  
  66.      /* I suppose that this is true */
  67.      if (getuid() != 0)
  68.        {
  69.           fprintf (stderr,"Must be root\n");
  70.           exit (214);
  71.        }
  72.  
  73.      while (((option = getopt (argc, argv, "x:n:mz?")) != NONOPT)
  74.              || optarg != NULL)
  75.        {
  76.           switch (option)
  77.             {
  78.                /* Set the debug level */
  79.                case 'x':
  80.                     debuglvl = atoi (optarg);
  81.                     break;
  82.  
  83.               /* Set a newsgroup that is forced, if this is just a single
  84.                  article */
  85.                case 'n':
  86.                     strcpy (initng, optarg);
  87.                     break;
  88.  
  89.                /* Force logging to standard output with no reguard to the
  90.                   debugging level */
  91.                case 'z':
  92.                     zflag++;
  93.                     break;
  94.  
  95.                /* Must be the file to process */
  96.                case NONOPT:
  97.                     strcpy (filename, optarg);
  98.                     break;
  99.  
  100.                case '?':                                   /* Help */
  101.                default:
  102.                     usage();
  103.                     break;
  104.             }
  105.        }
  106.  
  107.      if (getparam() == FALSE)
  108.           exit (ABORT);
  109.  
  110.      if ((logdir = getenv ("LOGDIR")) != NULL)
  111.           logdir = strdup (logdir);
  112.      else
  113.           logdir = LOGDIR;
  114.  
  115.      if ((newsdir = getdirs ("newsdir")) == NULL)
  116.           fatal ("newsdir not in Parameters");
  117.  
  118.      /* Set up the log file.  The fprintf below is important, as it makes sure
  119.         that standard error has been opened */
  120.  
  121.      if (zflag  ||  debuglvl > 4)
  122.        {
  123.           fprintf (stderr, "\nLogging to stderr\n");
  124.           inizlog ("rnews", 3);
  125.        }
  126.      else
  127.           inizlog ("rnews", 1);
  128.  
  129.      /* Get the groups from the active file */
  130.      g = getgroups();
  131.  
  132.      if (debuglvl > 5)
  133.           for (gg = g; gg != NULL; gg = gg->mbuf_next)
  134.            {
  135.                sprintf (lbuf, "ACTIVE IN: %s, %d, %d",
  136.                               ((struct groups *)gg->cbuf)->name,
  137.                               ((struct groups *)gg->cbuf)->min,
  138.                               ((struct groups *)gg->cbuf)->max);
  139.                log (lbuf);
  140.            }
  141.  
  142.     /* Got to be able to open the file */
  143.      if ((fd = open (filename, 1)) < 0)
  144.        {
  145.           sprintf (lbuf, "Can't open '%s'", filename);
  146.           log (lbuf);
  147.           exit (1);
  148.        }
  149.  
  150.      if (debuglvl > 3)
  151.        {
  152.           sprintf (lbuf, "Opened '%s'", filename);
  153.           log (lbuf);
  154.        }
  155.  
  156.      /* Hopefully the first bit of the file will tell us what sort of
  157.         thing it is */
  158.  
  159.      if ((e = read (fd, buf, BUFSIZ-1)) <= 0)
  160.        {
  161.           sprintf (lbuf, "Can't read from '%s'", filename);
  162.           log (lbuf);
  163.           exit (1);
  164.        }
  165.  
  166.      /* Ok, it seems to be a compressed file, possibly batched */
  167.      if (strncmp (buf, "#! cunbatch", 11) == 0)
  168.        {
  169.           if (debuglvl > 1)
  170.                log ("A compressed news file");
  171.  
  172.           /* Ok, move to the proper place in the file to begin decompression
  173.            */
  174.  
  175.           lseek (fd, 12l, 0);
  176.  
  177.           /* Save stdin, stdout and close the originals */
  178.           savein = dup (0);
  179.           saveout = dup (1);
  180.           close (0);
  181.           close (1);
  182.  
  183.           /* Try making the file's fd stdin, fail if we can't */
  184.           if (dup (fd) != 0)
  185.             {
  186.               log ("Can't dup fd 0");
  187.               exit (1);
  188.             }
  189.  
  190.           /* The pipe better be stdout !!! */
  191.  
  192.           if ((pipefd = open ("/pipe", 3)) != 1)
  193.             {
  194.                log ("Can't open /pipe");
  195.                exit (1);
  196.             }
  197.  
  198.           /* Fork compress, complain otherwise */
  199.           if ((p = os9fork ("compress", 3, "-d\n", 0, 0, 0)) < 0)
  200.             {
  201.                log ("Could not fork compress");
  202.                exit (1);
  203.             }
  204.  
  205.           /* Increase my priority, hopefully, above compress.
  206.  
  207.              The theory is that we will spend most of our time processing and
  208.               writing the article file, rather then reading from the pipe.
  209.               And when we read from the pipe, we aren't doing anything else
  210.               anyway [i.e. possibly sleeping on I/O].  So, don't take up CPU
  211.               time on compress, because it will be given the CPU when needed
  212.               anyway.   This may all be nuts, however....
  213.  
  214.              I've noted that making the priority the same makes for terrible
  215.              performance */
  216.  
  217.           setpr (getpid(), 200);
  218.           setpr (p, 100);
  219.  
  220.           /* It is important to close the file, on our side, or the end of
  221.               file on the pipe won't be detected. */
  222.  
  223.           close (0);
  224.  
  225.           /* Unredirect the file descriptors.  More arcane stuff, you really
  226.              shouldn't have to do this */
  227.  
  228.           pipefd = dup (1);
  229.           close (1);
  230.           dup (savein);
  231.           dup (saveout);
  232.  
  233.           /* Make a FILE pointer for the pipefd */
  234.           if ((batchfile = fdopen (pipefd, "r+")) == NULL)
  235.             {
  236.                log ("Couldn't fdopen the pipe fd");
  237.                exit (1);
  238.             }
  239.           setbuf (batchfile, bigbuf);
  240.  
  241.           /* Get the first line, which may indicate that this is a batch of
  242.              articles */
  243.  
  244.           if (getline (batchfile, buf) == -1)
  245.             {
  246.                log ("Nothing on the pipe");
  247.                exit (1);
  248.             }
  249.        }
  250.      else
  251.        {
  252.           /* Must not be compressed.  This is also the place where one might
  253.              process other compression schemes, like lha.  In general, one
  254.              should check for each type of compression before assuming that
  255.              the file is uncompressed */
  256.  
  257.           if (debuglvl > 1)
  258.                log ("An uncompressed news file");
  259.  
  260.           /* Rewind the file and get the size, so we can pass it along, if
  261.              needed */
  262.  
  263.           lseek (fd, 0l, 0);
  264.  
  265.           if (_gs_gfd (fd, &fdes, sizeof (fdes)) != -1)
  266.                length = (long)fdes.fd_fsize;
  267.  
  268.           /* Make a FILE pointer out of the file fd, instead of the pipe, as
  269.              above */
  270.  
  271.           if ((batchfile = fdopen (fd, "r")) == NULL)
  272.             {
  273.                log ("Can't fdopen news file");
  274.                exit (1);
  275.             }
  276.           setbuf (batchfile, bigbuf);
  277.  
  278.           /* Get a line, which could mean that this is a batch of articles */
  279.           getline (batchfile, buf);
  280.        }
  281.  
  282.      /* Ok, we seem to have a batch of articles.  Process them, as such */
  283.  
  284.      if (strncmp (buf, "#! rnews ", 9) == 0)
  285.        {
  286.           if (debuglvl > 1)
  287.                log ("A batch of news articles");
  288.  
  289.           procbatch (batchfile, buf, g);
  290.        }
  291.      else
  292.        {
  293.           /* Not a batch of articles, assume that it is a single article */
  294.           if (debuglvl > 1)
  295.                log ("A single news article");
  296.  
  297.           procart (batchfile, buf, initng, g, length);
  298.        }
  299.  
  300.      /* Put the updated active file back */
  301.      if (debuglvl > 3)
  302.           log ("Updating active file");
  303.  
  304.      putgroups (g);
  305.  
  306.      /* Clean things up */
  307.      if (debuglvl > 4)
  308.           log ("Exiting.....");
  309.  
  310.      fclose (batchfile);
  311.      close (pipefd);
  312.      close (fd);
  313.      wait (0);
  314.  
  315.      /* Close up the log */
  316.      deinizlog();
  317.      exit (0);
  318. }
  319.  
  320.  
  321.  
  322. /* Cheap fatal */
  323.  
  324. int fatal (s)
  325. char *s;
  326. {
  327.     fprintf (stderr, "'%s'\n");
  328.     exit (ABORT);
  329. }
  330.  
  331.  
  332.  
  333. /* Cheaper usage */
  334.  
  335. int usage()
  336. {
  337.      fprintf (stderr,
  338.               "rnews [-x debug_level] [-n inital_newsgroup] [-z] newsfile\n");
  339.      exit (1);
  340. }
  341.