home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / duucp-1.17 / AU-117b4-src.lha / src / news / forwardnews.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-27  |  10.7 KB  |  547 lines

  1. /*
  2.  *  FORWARDNEWS.C
  3.  *
  4.  *  (C)Copyright 1990, Mark R. Rinfret, All Rights Reserved
  5.  *
  6.  *  Author:    Mark R. Rinfret
  7.  *
  8.  *  This module is an extension to the UUCP rnews program. It provides a
  9.  *  primitive mechanism for forwarding news articles to other sites.
  10.  */
  11.  
  12. #include <exec/types.h>
  13. #include <dos/dos.h>
  14.  
  15. #include <clib/dos_protos.h>
  16. #include <clib/exec_protos.h>
  17.  
  18. #include <pragmas/dos_pragmas.h>
  19. #include <pragmas/exec_pragmas.h>
  20.  
  21. #include <errno.h>
  22. #include <ctype.h>
  23. #include <log.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <time.h>
  28.  
  29. #include "version.h"
  30. #include "config.h"
  31.  
  32. IDENT (".07");
  33.  
  34. #define iswhite(c)  (c == ' ' || c == '\t')
  35.  
  36. #ifdef PROCDEBUG
  37. #define D(x)    printf x
  38. #else
  39. #define D(x)
  40. #endif
  41.  
  42. typedef struct FwdPat {
  43.     struct FwdPat   *nextPattern;
  44.     char        *pattern;
  45. } FwdPat;
  46.  
  47. typedef struct ForwardList {
  48.     struct ForwardList    *nextSystem;
  49.     char        *sysName;
  50.     FwdPat        *firstPattern;
  51.     FwdPat        *lastPattern;
  52.     short        aliasFlag;
  53. } ForwardList;
  54.  
  55. static ForwardList    *firstSystem;
  56. static ForwardList    *lastSystem;
  57. static char        inString [256];
  58.  
  59. static char        *DupString (const char *s);
  60. static ForwardList    *NewForwardList (const char *name, ForwardList *);
  61. static FwdPat        *NewPattern (const char *s);
  62. static char        *NextPattern (char *in, char *out, int *length);
  63. static void        ParseSystem (FILE *sysFile, char *firstLine,
  64.                     ForwardList *system);
  65. static int        wildcmp (const char *wild, const char *name);
  66.  
  67. /*
  68.  *  FUNCTION
  69.  *    DupString - make a copy of a string.
  70.  *
  71.  *  SYNOPSIS
  72.  *    static char *DupString(const char *s);
  73.  *
  74.  *  DESCRIPTION
  75.  *    DupString creates a dynamically-allocated copy of string <s>.
  76.  *    It returns a pointer to the string or NULL if it fails.
  77.  */
  78.  
  79. static char *
  80. DupString (const char *s)
  81. {
  82.     char
  83.         *p;
  84.  
  85.     if (p = malloc (strlen (s) + 1)) {
  86.         strcpy (p, s);
  87.     }
  88.     return p;
  89. }
  90.  
  91. /*
  92.  *  FUNCTION
  93.  *    ForwardArticle - forward article to selected sites.
  94.  *
  95.  *  SYNOPSIS
  96.  *    void ForwardArticle(const char *base, long bytes)
  97.  *
  98.  *  DESCRIPTION
  99.  *    This function forwards an article to sites requesting it.
  100.  *    The article is forwarded to any site whos grouplist includes
  101.  *    one of the groups in the article Newsgroups: line.
  102.  *
  103.  *    The article will NOT be forwarded to any site already present
  104.  *    in the Path: header.
  105.  *
  106.  *  INPUTS
  107.  *    const char *base;    entire article, newlines and all,
  108.  *                buffer terminated by a \0
  109.  *
  110.  *    long bytes;        number of bytes in the buffer (so we
  111.  *                don't have to call strlen())
  112.  *
  113.  */
  114.  
  115. void
  116. ForwardArticle (char *base, long bytes, char *articleName)
  117. {
  118.     FILE
  119.         *batchFile;
  120.     static char
  121.         batchFileName [256];
  122.     FwdPat
  123.         *patternNode;
  124.     ForwardList
  125.         *system;
  126.     char
  127.         *path = DupHeader (base, "Path:");
  128.     BPTR
  129.         lock;
  130.  
  131.     if (path == NULL) {
  132.         ulog (-1, "ForwardArticle: no memory!");
  133.         return;
  134.     }
  135.  
  136.     D (("ForwardArticle: article = '%s'\n", articleName));
  137.  
  138.     for (system = firstSystem; system; system = system->nextSystem) {
  139.         if (system->aliasFlag)
  140.             continue;
  141.  
  142.         D (("ForwardArticle: checking system '%s' (%s)\n",
  143.                system->sysName, system->firstPattern ? "has pattern list" : "empty pattern list"));
  144.         /*
  145.          *  Make sure the system does not appear in path (allows us
  146.          *  to forward both upstream and downstream).
  147.          *  A Path line MUST exist.
  148.          *  Check possible alternates
  149.          */
  150.  
  151.         {
  152.             ForwardList
  153.                 *scan;
  154.  
  155.             for (scan = system; scan;) {
  156.                 sprintf (batchFileName, "%s!", scan->sysName);
  157.                 if (stristr (path, batchFileName))
  158.                     break;
  159.                 sprintf (batchFileName, "%s.", scan->sysName);
  160.                 if (stristr (path, batchFileName))
  161.                     break;
  162.                 if (scan = scan->nextSystem) {
  163.                     if (scan->aliasFlag == 0)
  164.                         scan = NULL;
  165.                 }
  166.             }
  167.             if (scan) {
  168.                 ulog (25, "will not forward %s to %s", articleName, system->sysName);
  169.                 continue;
  170.             }
  171.         }
  172.  
  173.         /*
  174.          *  Check group wildcard against group list
  175.          */
  176.  
  177.         {
  178.             int
  179.                 match = 0;
  180.             char
  181.                 *grp;
  182.  
  183.             ScanHeader (base, "Newsgroups:");
  184.             while (match == 0 && (grp = ScanNext ())) {
  185.                 for (patternNode = system->firstPattern; patternNode; patternNode = patternNode->nextPattern) {
  186.                     if (patternNode->pattern [0] == '-' || patternNode->pattern [0] == '!') {
  187.                         if (wildcmp (patternNode->pattern + 1, grp))
  188.                             match = 0;
  189.                     }
  190.                     else {
  191.                         if (wildcmp (patternNode->pattern, grp))
  192.                             match = 1;
  193.                     }
  194.                 }
  195.             }
  196.  
  197.             if (match == 0)
  198.                 continue;
  199.         }
  200.  
  201.         /*
  202.          *  Since match was found append forwarding info to batch
  203.          */
  204.         D (("ForwardArticle: got a match!\n"));
  205.         strcpy (batchFileName, MakeConfigPath (UUSPOOL, "batch"));
  206.  
  207.         /*
  208.          *  Create UUSPOOL:Batch if it does not exist.    If
  209.          *  create fails we will get an error message down
  210.          *  a bit more when we attempt to open the sub file.
  211.          */
  212.  
  213.         if ((lock = Lock (batchFileName, SHARED_LOCK)) == NULL)
  214.             lock = CreateDir (batchFileName);
  215.         if (lock)
  216.             UnLock (lock);
  217.  
  218.         /*
  219.          * Create/append batching file
  220.          */
  221.  
  222.         strcat (batchFileName, "/");
  223.         strcat (batchFileName, system->sysName);
  224.         LockFile (batchFileName);
  225.         batchFile = fopen (batchFileName, "a");
  226.         if (!batchFile) {
  227.             ulog (-1, "Can't open batch file %s (%ld)",
  228.                 batchFileName, IoErr ());
  229.             fprintf (stderr, "rnews: Can't open batch file '%s'!\n",
  230.                 batchFileName);
  231.         }
  232.         else {
  233.             fprintf (batchFile, "%s\n", articleName);
  234.             fclose (batchFile);
  235.         }
  236.         UnLockFile (batchFileName);
  237.     }
  238.  
  239.     free (path);
  240.     return;
  241. }
  242.  
  243. /*
  244.  *  FUNCTION
  245.  *    GetForwardingInfo - build list of systems to receive news.
  246.  *
  247.  *  SYNOPSIS
  248.  *    int GetForwardingInfo (void);
  249.  *
  250.  *  DESCRIPTION
  251.  *    This function initializes the ForwardNews package, building news
  252.  *    forwarding lists for sites to  receive news from our machine.
  253.  *
  254.  *    The file UULIB:sys defines the article selection criteria for each
  255.  *    machine. Files named UUSPOOL/batch/<system> will be updated to contain
  256.  *    article lists which are then batched by a news batching program.
  257.  *
  258.  *    If this function is successful, it will return zero. Otherwise, -1
  259.  *    will be returned.
  260.  */
  261.  
  262. int
  263. GetForwardingInfo (void)
  264. {
  265.     char
  266.         c;
  267.     char
  268.         *s1, *s2;
  269.     FILE
  270.         *sysFile = NULL;
  271.     ForwardList
  272.         *sysNode = NULL;
  273.  
  274.     sysFile = fopen (MakeConfigPath (UULIB, "sys"), "r");
  275.  
  276.     if (sysFile == NULL) {
  277.         ulog (-1, "Can't open UULIB:Sys");
  278.         return 0;
  279.     }
  280.  
  281.     while (fgets (inString, sizeof (inString), sysFile)) {
  282.         inString [strlen (inString) - 1] = '\0';
  283.  
  284.         s1 = inString;
  285.  
  286.         while ((c = *s1) && iswhite (c))
  287.             s1++;
  288.         if (c == '\0' || c == '#')
  289.             continue;
  290.  
  291.         if (!isalpha (c))
  292.             goto bad_line;
  293.  
  294.         /*
  295.          *  Scan for systemA:systemB:systemC: ...systemZ: newsgroups ..
  296.          */
  297.  
  298.         sysNode = NULL;
  299.         while (s2 = strchr (s1, ':')) {
  300.             *s2 = 0;
  301.             sysNode = NewForwardList (s1, sysNode);
  302.             if (sysNode == NULL)
  303.                 return -1;
  304.             D (("System: %08lx '%s'\n", sysNode, s1));
  305.             s1 = s2 + 1;
  306.         }
  307.  
  308.         if (sysNode == NULL) {
  309. bad_line:
  310.             fprintf (stderr, "Bad sys line ignored:\n%s\n", inString);
  311.             ulog (-1, "Bad UULIB:Sys line ignored:'%s'", inString);
  312.             continue;
  313.         }
  314.  
  315.         ParseSystem (sysFile, s1, sysNode);
  316.     }
  317.  
  318.     return 0;
  319. }
  320.  
  321. /*
  322.  *  Create a new ForwardList node and append to our global system list.
  323.  *  If the passed ForwardList node is null, we return the new node.  If
  324.  *  the passed forwardlist node is not null, we return it instead of the
  325.  *  new node and set the alias flag in the new node.
  326.  */
  327.  
  328. static ForwardList *
  329. NewForwardList (const char *name, ForwardList *base)
  330. {
  331.     ForwardList
  332.         *list;
  333.  
  334.     if (list = calloc (sizeof (ForwardList), 1)) {
  335.         if (list->sysName = DupString (name)) {
  336.             if (firstSystem == NULL)
  337.                 firstSystem = list;
  338.             else
  339.                 lastSystem->nextSystem = list;
  340.             lastSystem = list;
  341.         }
  342.         else {
  343.             free (list);
  344.             list = NULL;
  345.         }
  346.     }
  347.  
  348.     if (list == NULL) {
  349.         fprintf (stderr, "forwardnews: out of memory!");
  350.         ulog (-1, "Can't allocate ForwardList: Out of memory");
  351.         return NULL;
  352.     }
  353.  
  354.     if (base) {
  355.         list->aliasFlag = 1;
  356.         return base;
  357.     }
  358.  
  359.     return list;
  360. }
  361.  
  362. static FwdPat *
  363. NewPattern (const char *s)
  364. {
  365.     FwdPat
  366.         *pNode;
  367.  
  368.     if (!(pNode = calloc (sizeof (struct FwdPat), 1)) ||
  369.         !(pNode->pattern = DupString (s))) {
  370.  
  371.         fprintf (stderr, "NewPattern: no memory!\n");
  372.         ulog (-1, "NewPattern: no memory!");
  373.         return NULL;
  374.     }
  375.  
  376.     return pNode;
  377. }
  378.  
  379. static char *
  380. NextPattern (char *in, char *out, int *length)
  381. {
  382.     char
  383.         c,
  384.         *s1 = out;
  385.  
  386.     if (*in == ',')
  387.         ++in;
  388.     while (iswhite (*in))
  389.         ++in;
  390.  
  391.     *length = 0;
  392.     while (c = *in) {
  393.         if (c == '\\' || c == ',' || c == '\n')
  394.             break;
  395.  
  396.         ++in;                /* Advance beyond current char. */
  397.         if (!iswhite (c)) {
  398.             *s1++ = c;
  399.             ++*length;
  400.         }
  401.     }
  402.     *s1 = '\0';                         /* Terminate with a NULL. */
  403.  
  404.     return in;
  405. }
  406.  
  407. void
  408. ParseSystem (FILE *sysFile, char *firstLine, ForwardList *system)
  409. {
  410.     int
  411.         length,
  412.         patternLength;
  413.     char
  414.         pattern [80];
  415.     FwdPat
  416.         *pNode;
  417.     char
  418.         *s1,
  419.         *theLine = firstLine;
  420.  
  421.     do {
  422.         s1 = theLine;
  423.         while (*s1 == ' ' || *s1 == '\t')
  424.             s1++;
  425.  
  426.         if (*s1 == '\n' || *s1 == '#') {
  427.             length = 0;
  428.         }
  429.         else {
  430.             length = strlen (s1);
  431.             if (s1 [length - 1] == '\n') {
  432.                 /* Delete trailing newline. */
  433.                 s1 [--length] = '\0';
  434.             }
  435.         }
  436.  
  437.         if (length > 0) {
  438.             do {
  439.                 s1 = NextPattern (s1, pattern, &patternLength);
  440.                 if (patternLength) {
  441.                     D (("ParseSystem - next pattern: '%s'\n", pattern));
  442.                     pNode = NewPattern (pattern);
  443.                     if (pNode == NULL) {
  444.                         ulog (-1, "NewPattern failed");
  445.                         return;
  446.                     }
  447.  
  448.                     /* Add this to our forward-linked list. */
  449.                     if (system->firstPattern == NULL)
  450.                         system->firstPattern = pNode;
  451.                     else
  452.                         system->lastPattern->nextPattern = pNode;
  453.                     system->lastPattern = pNode;
  454.                 }
  455.             } while (*s1 == ',');
  456.  
  457.             if (*s1 != '\\')
  458.                 break;
  459.         }
  460.  
  461.         theLine = inString;
  462.     } while (fgets (inString, sizeof (inString), sysFile));
  463.  
  464.     return;
  465. }
  466.  
  467.  
  468. /*  FUNCTION
  469.     wildcmp - compare a wild card name with a normal name.
  470.  
  471.     SYNOPSIS
  472.     int wildcmp(const char *wild, const char *name);
  473.  
  474.     DESCRIPTION
  475.     Argument <wild>, a string containing wild card characters, is
  476.     compared against <name>, a string containing no wild card
  477.     characters. If the strings match, a one (1) is returned.
  478.     Otherwise, a zero (0) is returned.
  479.  
  480.     AUTHOR
  481.     Matt Dillon
  482.  */
  483.  
  484. #define MAXB   8
  485.  
  486. int
  487. wildcmp (const char *wild, const char *name)
  488. {
  489.     register char
  490.         *w = wild;
  491.     register char
  492.         *n = name;
  493.     char
  494.         *back [MAXB] [2];
  495.     register char
  496.         s1, s2;
  497.     int
  498.         bi = 0;
  499.  
  500.     while (*n || *w){
  501.         switch (*w) {
  502.             case '*':
  503.                 if (bi == MAXB) {
  504.                     D (("Too many levels of '*'\n"));
  505.                     return 0;
  506.                 }
  507.                 back[bi][0]= w;
  508.                 back[bi][1]= n;
  509.                 ++bi;
  510.                 ++w;
  511.                 continue;
  512. goback:
  513.                 --bi;
  514.                 while (bi >= 0 && *back[bi][1] == '\0')
  515.                     --bi;
  516.                 if (bi < 0)
  517.                     return 0;
  518.                 w = back[bi][0] + 1;
  519.                 n = ++back[bi][1];
  520.                 ++bi;
  521.                 continue;
  522.             case '?':
  523.                 if (!*n){
  524.                     if (bi)
  525.                         goto goback;
  526.                     return 0;
  527.                 }
  528.                 break;
  529.             default:
  530.                 s1 = (*n >= 'A' && *n <= 'Z') ? *n - 'A' + 'a' : *n;
  531.                 s2 = (*w >= 'A' && *w <= 'Z') ? *w - 'A' + 'a' : *w;
  532.                 if (s1 != s2){
  533.                     if (bi)
  534.                         goto goback;
  535.                     return 0;
  536.                 }
  537.                 break;
  538.         }
  539.         if (*n)
  540.             ++n;
  541.         if (*w)
  542.             ++w;
  543.     }
  544.  
  545.     return 1;
  546. }
  547.