home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / duucp-1.17 / AU-117b4-src.lha / src / news / batchnews.c next >
Encoding:
C/C++ Source or Header  |  1993-12-27  |  8.8 KB  |  448 lines

  1. /*#define PROCDEBUG*/
  2. /*
  3. **  BATCHNEWS.C
  4. **
  5. **  BATCHNEWS [-h hostname] [-t temp-directory]
  6. **
  7. **  (C)Copyright 1990, Mark R. Rinfret, All Rights Reserved
  8. **
  9. **  Author:    Mark R. Rinfret, September 1990
  10. **  library compress routines melded in Apr 1991, Matt Dillon
  11. **  Modified May 1991 by Henning Schmiedehausen
  12. **  Changes Copyright 1993 by Michael B. Smith. All Rights Reserved.
  13. **
  14. **  The batchnews program allows you to forward news to other sites.
  15. **  It expects to find a text file named UUSpool:batch/<system>
  16. **  where <system> is the name of the system to receive the news.
  17. **
  18. **  The file UULib:sys is the configuration file which determines the
  19. **  newsgroups that are to be forwarded to <system>.
  20. **
  21. **  Options
  22. **
  23. **    -h    Normally, BatchNews batches news for all hosts. The -h
  24. **        argument allows a single host to be specified.
  25. **
  26. **    -t    The -t argument allows the user to specify where temporary
  27. **        spool-files are to be built. Normally, these are in UUNews.
  28. **        Specifying T: can speed up processing significantly, at a
  29. **        cost in higher memory usage.
  30. */
  31.  
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <errno.h>
  36. #include <ctype.h>
  37. #include <log.h>
  38. #include <exec/types.h>
  39. #include <dos/dos.h>
  40. #include <clib/dos_protos.h>
  41. #include <owndevunit.h>
  42.  
  43. #include "version.h"
  44. #include "config.h"
  45.  
  46. IDENT (".10");
  47.  
  48. static char
  49.     TmpBuf [2048],
  50.     TmpBuf2 [256];
  51. char
  52.     *TmpDir = NULL,
  53.     *SingleHost = NULL,
  54.     *NewsDir = NULL,
  55.     *WKName = NULL;
  56. struct Library
  57.     *OwnDevUnitBase = NULL;
  58. int
  59.     _bufsiz = 8192,
  60.     SpoolSize;
  61. short
  62.     Bits = 12;
  63.  
  64. #define PROG_NAME "BatchNews"
  65.  
  66. #ifdef PROCDEBUG
  67. #define PROC(x)     const char *_proc = x; printf ("%s: enter\n", _proc)
  68. #define D(x)        printf ("%s: ", _proc); printf x
  69. #else
  70. #define PROC(x)
  71. #define D(x)
  72. #endif
  73.  
  74. void myexit (void);
  75. void BatchNews (const char *dirName, const char *systemName);
  76. void SpoolBatch (const char *systemName);
  77.  
  78. void
  79. usage (const char *name)
  80. {
  81.     fprintf (stderr, "usage: %s [-t temp-directory] [-h hostname]\n", name);
  82.  
  83.     exit (30);
  84. }
  85.  
  86. int
  87. main (int ac, char **av)
  88. {
  89.     int
  90.         j;
  91.     char
  92.         *ptr,
  93.         *batchDirName;
  94.     struct FileInfoBlock
  95.         *fib = malloc (sizeof (struct FileInfoBlock));
  96.     BPTR
  97.         lock;
  98.     PROC ("main");
  99.  
  100.     LogProgram = PROG_NAME;
  101.     atexit (myexit);
  102.     if ((OwnDevUnitBase = OpenLibrary (ODU_NAME, 0)) == NULL) {
  103.         fprintf (stderr, "Couldn't open library '%s'\n", ODU_NAME);
  104.         exit (20);
  105.     }
  106.  
  107.     if (!fib) {
  108.         ulog (-1, "No mem!");
  109.         exit (30);
  110.     }
  111.  
  112.     for (j = 1; j < ac; j++) {
  113.         ptr = av [j];
  114.         if (*ptr != '-')
  115.             usage (av [0]);
  116.         ptr++;
  117.         switch (*ptr) {
  118.             case 'h':
  119.                 ptr++;
  120.                 if (*ptr)
  121.                     SingleHost = ptr;
  122.                 else
  123.                     SingleHost = av [++j];
  124.                 D (("SingleHost is '%s'\n", SingleHost));
  125.                 break;
  126.  
  127.             case 't':
  128.                 ptr++;
  129.                 if (*ptr)
  130.                     TmpDir = ptr;
  131.                 else
  132.                     TmpDir = av [++j];
  133.                 D (("TmpDir is '%s'\n", TmpDir));
  134.                 break;
  135.  
  136.             default:
  137.                 usage (av [0]);
  138.         }
  139.     }
  140.  
  141.     LockFile ("BATCHNEWS");
  142.  
  143.     NewsDir   = GetConfigDir (UUNEWS);
  144.     Bits      = (short) atoi (GetConfig (BATCHBITS, "12"));
  145.     SpoolSize = atoi (GetConfig (SPOOLSIZE, "65000"));
  146.  
  147.     if (Bits < 12 || Bits > 16)
  148.         Bits = 12;
  149.  
  150.     if (SpoolSize <= 100)
  151.         SpoolSize = 16000;
  152.  
  153.     if (safe_chdir (NewsDir)) {
  154.         ulog (-1, "BatchNews: NewsDir '%s' doesn't exist; quitting", NewsDir);
  155.         exit (20);
  156.     }
  157.  
  158.     ptr = TmpFileName ("news-work");
  159.     if (TmpDir) {
  160.         int
  161.             i = strlen (TmpDir);
  162.         char
  163.             *p = TmpDir + (i - 1);
  164.  
  165.         WKName = malloc (strlen (ptr) + i + 3);
  166.         if (!WKName) {
  167.             ulog (-1, "No mem!");
  168.             exit (30);
  169.         }
  170.  
  171.         sprintf (WKName, "%s%s%s",
  172.             TmpDir,
  173.             (*p == ':' || *p == '/') ? "" : "/",
  174.             ptr);
  175.     }
  176.     else {
  177.         WKName = strdup (ptr);
  178.         if (!WKName) {
  179.             ulog (-1, "No mem!");
  180.             exit (30);
  181.         }
  182.     }
  183.  
  184.     batchDirName = strdup (MakeConfigPath (UUSPOOL, "batch"));
  185.     if (!batchDirName) {
  186.         ulog (-1, "No mem!");
  187.         exit (30);
  188.     }
  189.     lock = Lock (batchDirName, SHARED_LOCK);
  190.     if (!lock) {
  191.         ulog (-1,"Where is batch directory '%s'?", batchDirName);
  192.         exit (20);
  193.     }
  194.  
  195.     if (SingleHost) {
  196.         if (is_in_L_sys_file (SingleHost))
  197.             BatchNews (batchDirName, SingleHost);
  198.         else
  199.             ulog (-1, "Invalid host name '%s'", SingleHost);
  200.     }
  201.     else {
  202.         if (Examine (lock, fib)) {
  203.             while (ExNext (lock, fib)) {
  204.                 if (fib->fib_DirEntryType > 0)
  205.                     continue;
  206.                 D (("scan: '%s'\n", fib->fib_FileName));
  207.  
  208.                 if (is_in_L_sys_file (fib->fib_FileName)) {
  209.                     BatchNews (batchDirName, fib->fib_FileName);
  210.                 }
  211.             }
  212.         }
  213.     }
  214.     UnLock (lock);
  215.  
  216.     D (("exit\n"));
  217.     exit (0);
  218. }
  219.  
  220. void
  221. myexit (void)
  222. {
  223.     PROC ("myexit");
  224.  
  225.     UnLockFiles ();
  226.  
  227.     if (OwnDevUnitBase) {
  228.         CloseLibrary (OwnDevUnitBase);
  229.         OwnDevUnitBase = NULL;
  230.     }
  231.  
  232.     D (("exit\n"));
  233.     return;
  234. }
  235.  
  236. void
  237. BatchNews (const char *dirName, const char *systemName)
  238. {
  239.     static char
  240.         batchFileName [128];
  241.     struct FileInfoBlock
  242.         *fib = malloc (sizeof (struct FileInfoBlock));
  243.     char
  244.         *newsFileName = NULL,
  245.         *nodename   = FindConfig (NODENAME),
  246.         *domainname = FindConfig (DOMAINNAME),
  247.         *domainpath = GetConfig (DOMAINPATH, "N");
  248.     FILE
  249.         *newsFile = NULL,
  250.         *workFile = NULL,
  251.         *batchFile = NULL;
  252.     BPTR
  253.         lock = 0;
  254.     int
  255.         fileSize,
  256.         length,
  257.         ret = 0,
  258.         totalSize,
  259.         workPos;
  260.  
  261.     PROC ("BatchNews");
  262.     D (("system '%s'\n", systemName));
  263.  
  264.     if (!fib) {
  265.         ulog (-1, "No mem!");
  266.         return;
  267.     }
  268.  
  269.     if (domainpath [0] == '1' ||
  270.         domainpath [0] == 'y' ||
  271.         domainpath [0] == 'Y') {
  272.         domainpath = domainname;
  273.     }
  274.     else {
  275.         domainpath = "";
  276.     }
  277.  
  278.     strcpy (batchFileName, dirName);
  279.     strcat (batchFileName, "/");
  280.     strcat (batchFileName, systemName);
  281.     batchFile = fopen (batchFileName, "r");
  282.     if (!batchFile) {
  283.         if (SingleHost)
  284.             ulog (-1, "No news to batch for '%s'", SingleHost);
  285.         D (("leaving, can't open '%s'\n", batchFileName));
  286.         goto done;          /* Try later? */
  287.     }
  288.  
  289.     workFile = fopen (WKName, "w");
  290.     if (!workFile) {
  291. no_workfile:
  292.         ret = errno;
  293.         ulog (-1, "Failed to open work file '%s'\n", WKName);
  294.         D (("leaving, Can't open '%s'\n", WKName));
  295.         goto done;
  296.     }
  297.  
  298.     totalSize = 0;
  299.  
  300.     while (fgets (TmpBuf, sizeof (TmpBuf), batchFile)) {
  301.         D (("file %s", TmpBuf));
  302.  
  303.         if (*TmpBuf == '\0' || *TmpBuf == '\n')
  304.             continue;
  305.  
  306.         length = strlen (TmpBuf);
  307.  
  308.         if (TmpBuf [length - 1] == '\n')
  309.             TmpBuf [--length] = '\0';  /* Drop trailing newline. */
  310.  
  311.         if (newsFileName = HandleHeirarchy (NewsDir, TmpBuf, 1)) {
  312.             strcpy (TmpBuf, newsFileName);
  313.             D (("%s\n", TmpBuf));
  314.             free (newsFileName);
  315.  
  316.             fileSize = -1;
  317.             if (lock = Lock (TmpBuf, SHARED_LOCK)) {
  318.                 if (Examine (lock, fib))
  319.                     fileSize = fib->fib_Size;
  320.                 UnLock (lock);
  321.             }
  322.  
  323.             if (fileSize < 0) {
  324.                 ulog (-1, "Article '%s' is missing (IoErr %ld)", TmpBuf, IoErr ());
  325.                 D (("Bad art name? '%s'\n", TmpBuf));
  326.                 continue;
  327.             }
  328.  
  329.             if (fileSize + totalSize + 64 > SpoolSize) {
  330.                 fclose (workFile);
  331.                 SpoolBatch (systemName);
  332.                 totalSize = 0;
  333.                 workFile = fopen (WKName, "w");  /* Re-open the work file. */
  334.                 if (!workFile)
  335.                     goto no_workfile;
  336.             }
  337.             newsFile = fopen (TmpBuf, "r");
  338.         }
  339.  
  340.         /*
  341.          *  newsFileName is invalid after this except for boolean checks
  342.          */
  343.  
  344.         if (newsFileName == NULL || newsFile == NULL)
  345.             continue;
  346.  
  347.         /*
  348.          *  Handle news file.  Delete Xref: lines, modify Path: lines,
  349.          *  copy rest.    Filesize is modified at seekback.
  350.          */
  351.  
  352.         workPos = ftell (workFile);
  353.         fprintf (workFile, "#! rnews %06ld\n", 0); /*  rewritten later */
  354.         fileSize = 0;
  355.  
  356.         while (fgets (TmpBuf, sizeof (TmpBuf) - 16, newsFile)) {
  357.             if (strnicmp (TmpBuf, "Xref:", 5) == 0)
  358.                 continue;
  359.             if (strnicmp (TmpBuf, "Path:", 5) == 0) {
  360.                 char
  361.                     *ptr = TmpBuf + 5;
  362.  
  363.                 while (*ptr == ' ' || *ptr == '\t')
  364.                     ++ptr;
  365.                 strins (ptr, "!");
  366.                 strins (ptr, domainpath);
  367.                 strins (ptr, nodename);
  368.                 D (("new Path %s\n", TmpBuf));
  369.             }
  370.             fputs (TmpBuf, workFile);
  371.             fileSize += strlen (TmpBuf);
  372.             if (TmpBuf [0] == '\n')
  373.                 break;
  374.         }
  375.  
  376.         while (fgets (TmpBuf, sizeof (TmpBuf) - 16, newsFile)) {
  377.             fputs (TmpBuf, workFile);
  378.             fileSize += strlen (TmpBuf);
  379.         }
  380.  
  381.         fclose (newsFile);
  382.         totalSize += fileSize;
  383.         fseek (workFile, workPos, 0);
  384.         fprintf (workFile,"#! rnews %06ld\n", fileSize);
  385.         fseek (workFile, 0, 2);
  386.     }
  387.  
  388. done:
  389.     if (workFile) {
  390.         fclose (workFile);
  391.         if (ret == 0 && totalSize)
  392.             SpoolBatch (systemName);
  393.     }
  394.     if (batchFile) {
  395.         fclose (batchFile);
  396.         remove (batchFileName);
  397.     }
  398.     free (fib);
  399.     remove (WKName);
  400.  
  401.     D (("exit\n"));
  402.     return;
  403. }
  404.  
  405. void
  406. SpoolBatch (const char *systemName)
  407. {
  408.     FILE
  409.         *fo;
  410.     int
  411.         r = -1;
  412.  
  413.     PROC ("SpoolBatch");
  414.     D (("compressing file '%s' bits = %ld\n", WKName, (int) Bits));
  415.  
  416.     sprintf (TmpBuf2, "%s.Z", WKName);
  417.     if (fo = fopen (TmpBuf2, "w")) {
  418.         fputs ("#! cunbatch\n", fo);
  419.         fflush (fo);
  420.         r = compress_from_file (WKName, fo, Bits);
  421.         fclose (fo);
  422.     }
  423.  
  424.     if (r == 0) {
  425.         remove (WKName);
  426.         rename (TmpBuf2, WKName);
  427.  
  428.     }
  429.     else {
  430.         remove (TmpBuf2);
  431.         ulog (-1, "compress failed, low memory or uncompressable file");
  432.         ulog (-1, "will proceed with an uncompressed batch");
  433.     }
  434.  
  435.     /* Submit it to uux for transmission to target system. */
  436.     sprintf (TmpBuf2, "%s %s \"%s!rnews\"",
  437.         GetConfigProgram (UUX),
  438.         WKName,
  439.         systemName
  440.     );
  441.  
  442.     D (("command '%s'\n", TmpBuf2));
  443.     system (TmpBuf2);
  444.  
  445.     D (("exit\n"));
  446.     return;
  447. }
  448.