home *** CD-ROM | disk | FTP | other *** search
- /*
- * FORWARDNEWS.C
- *
- * (C)Copyright 1990, Mark R. Rinfret, All Rights Reserved
- *
- * Author: Mark R. Rinfret
- *
- * This module is an extension to the UUCP rnews program. It provides a
- * primitive mechanism for forwarding news articles to other sites.
- */
-
- #include <exec/types.h>
- #include <dos/dos.h>
-
- #include <clib/dos_protos.h>
- #include <clib/exec_protos.h>
-
- #include <pragmas/dos_pragmas.h>
- #include <pragmas/exec_pragmas.h>
-
- #include <errno.h>
- #include <ctype.h>
- #include <log.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
-
- #include "version.h"
- #include "config.h"
-
- IDENT (".07");
-
- #define iswhite(c) (c == ' ' || c == '\t')
-
- #ifdef PROCDEBUG
- #define D(x) printf x
- #else
- #define D(x)
- #endif
-
- typedef struct FwdPat {
- struct FwdPat *nextPattern;
- char *pattern;
- } FwdPat;
-
- typedef struct ForwardList {
- struct ForwardList *nextSystem;
- char *sysName;
- FwdPat *firstPattern;
- FwdPat *lastPattern;
- short aliasFlag;
- } ForwardList;
-
- static ForwardList *firstSystem;
- static ForwardList *lastSystem;
- static char inString [256];
-
- static char *DupString (const char *s);
- static ForwardList *NewForwardList (const char *name, ForwardList *);
- static FwdPat *NewPattern (const char *s);
- static char *NextPattern (char *in, char *out, int *length);
- static void ParseSystem (FILE *sysFile, char *firstLine,
- ForwardList *system);
- static int wildcmp (const char *wild, const char *name);
-
- /*
- * FUNCTION
- * DupString - make a copy of a string.
- *
- * SYNOPSIS
- * static char *DupString(const char *s);
- *
- * DESCRIPTION
- * DupString creates a dynamically-allocated copy of string <s>.
- * It returns a pointer to the string or NULL if it fails.
- */
-
- static char *
- DupString (const char *s)
- {
- char
- *p;
-
- if (p = malloc (strlen (s) + 1)) {
- strcpy (p, s);
- }
- return p;
- }
-
- /*
- * FUNCTION
- * ForwardArticle - forward article to selected sites.
- *
- * SYNOPSIS
- * void ForwardArticle(const char *base, long bytes)
- *
- * DESCRIPTION
- * This function forwards an article to sites requesting it.
- * The article is forwarded to any site whos grouplist includes
- * one of the groups in the article Newsgroups: line.
- *
- * The article will NOT be forwarded to any site already present
- * in the Path: header.
- *
- * INPUTS
- * const char *base; entire article, newlines and all,
- * buffer terminated by a \0
- *
- * long bytes; number of bytes in the buffer (so we
- * don't have to call strlen())
- *
- */
-
- void
- ForwardArticle (char *base, long bytes, char *articleName)
- {
- FILE
- *batchFile;
- static char
- batchFileName [256];
- FwdPat
- *patternNode;
- ForwardList
- *system;
- char
- *path = DupHeader (base, "Path:");
- BPTR
- lock;
-
- if (path == NULL) {
- ulog (-1, "ForwardArticle: no memory!");
- return;
- }
-
- D (("ForwardArticle: article = '%s'\n", articleName));
-
- for (system = firstSystem; system; system = system->nextSystem) {
- if (system->aliasFlag)
- continue;
-
- D (("ForwardArticle: checking system '%s' (%s)\n",
- system->sysName, system->firstPattern ? "has pattern list" : "empty pattern list"));
- /*
- * Make sure the system does not appear in path (allows us
- * to forward both upstream and downstream).
- * A Path line MUST exist.
- * Check possible alternates
- */
-
- {
- ForwardList
- *scan;
-
- for (scan = system; scan;) {
- sprintf (batchFileName, "%s!", scan->sysName);
- if (stristr (path, batchFileName))
- break;
- sprintf (batchFileName, "%s.", scan->sysName);
- if (stristr (path, batchFileName))
- break;
- if (scan = scan->nextSystem) {
- if (scan->aliasFlag == 0)
- scan = NULL;
- }
- }
- if (scan) {
- ulog (25, "will not forward %s to %s", articleName, system->sysName);
- continue;
- }
- }
-
- /*
- * Check group wildcard against group list
- */
-
- {
- int
- match = 0;
- char
- *grp;
-
- ScanHeader (base, "Newsgroups:");
- while (match == 0 && (grp = ScanNext ())) {
- for (patternNode = system->firstPattern; patternNode; patternNode = patternNode->nextPattern) {
- if (patternNode->pattern [0] == '-' || patternNode->pattern [0] == '!') {
- if (wildcmp (patternNode->pattern + 1, grp))
- match = 0;
- }
- else {
- if (wildcmp (patternNode->pattern, grp))
- match = 1;
- }
- }
- }
-
- if (match == 0)
- continue;
- }
-
- /*
- * Since match was found append forwarding info to batch
- */
- D (("ForwardArticle: got a match!\n"));
- strcpy (batchFileName, MakeConfigPath (UUSPOOL, "batch"));
-
- /*
- * Create UUSPOOL:Batch if it does not exist. If
- * create fails we will get an error message down
- * a bit more when we attempt to open the sub file.
- */
-
- if ((lock = Lock (batchFileName, SHARED_LOCK)) == NULL)
- lock = CreateDir (batchFileName);
- if (lock)
- UnLock (lock);
-
- /*
- * Create/append batching file
- */
-
- strcat (batchFileName, "/");
- strcat (batchFileName, system->sysName);
- LockFile (batchFileName);
- batchFile = fopen (batchFileName, "a");
- if (!batchFile) {
- ulog (-1, "Can't open batch file %s (%ld)",
- batchFileName, IoErr ());
- fprintf (stderr, "rnews: Can't open batch file '%s'!\n",
- batchFileName);
- }
- else {
- fprintf (batchFile, "%s\n", articleName);
- fclose (batchFile);
- }
- UnLockFile (batchFileName);
- }
-
- free (path);
- return;
- }
-
- /*
- * FUNCTION
- * GetForwardingInfo - build list of systems to receive news.
- *
- * SYNOPSIS
- * int GetForwardingInfo (void);
- *
- * DESCRIPTION
- * This function initializes the ForwardNews package, building news
- * forwarding lists for sites to receive news from our machine.
- *
- * The file UULIB:sys defines the article selection criteria for each
- * machine. Files named UUSPOOL/batch/<system> will be updated to contain
- * article lists which are then batched by a news batching program.
- *
- * If this function is successful, it will return zero. Otherwise, -1
- * will be returned.
- */
-
- int
- GetForwardingInfo (void)
- {
- char
- c;
- char
- *s1, *s2;
- FILE
- *sysFile = NULL;
- ForwardList
- *sysNode = NULL;
-
- sysFile = fopen (MakeConfigPath (UULIB, "sys"), "r");
-
- if (sysFile == NULL) {
- ulog (-1, "Can't open UULIB:Sys");
- return 0;
- }
-
- while (fgets (inString, sizeof (inString), sysFile)) {
- inString [strlen (inString) - 1] = '\0';
-
- s1 = inString;
-
- while ((c = *s1) && iswhite (c))
- s1++;
- if (c == '\0' || c == '#')
- continue;
-
- if (!isalpha (c))
- goto bad_line;
-
- /*
- * Scan for systemA:systemB:systemC: ...systemZ: newsgroups ..
- */
-
- sysNode = NULL;
- while (s2 = strchr (s1, ':')) {
- *s2 = 0;
- sysNode = NewForwardList (s1, sysNode);
- if (sysNode == NULL)
- return -1;
- D (("System: %08lx '%s'\n", sysNode, s1));
- s1 = s2 + 1;
- }
-
- if (sysNode == NULL) {
- bad_line:
- fprintf (stderr, "Bad sys line ignored:\n%s\n", inString);
- ulog (-1, "Bad UULIB:Sys line ignored:'%s'", inString);
- continue;
- }
-
- ParseSystem (sysFile, s1, sysNode);
- }
-
- return 0;
- }
-
- /*
- * Create a new ForwardList node and append to our global system list.
- * If the passed ForwardList node is null, we return the new node. If
- * the passed forwardlist node is not null, we return it instead of the
- * new node and set the alias flag in the new node.
- */
-
- static ForwardList *
- NewForwardList (const char *name, ForwardList *base)
- {
- ForwardList
- *list;
-
- if (list = calloc (sizeof (ForwardList), 1)) {
- if (list->sysName = DupString (name)) {
- if (firstSystem == NULL)
- firstSystem = list;
- else
- lastSystem->nextSystem = list;
- lastSystem = list;
- }
- else {
- free (list);
- list = NULL;
- }
- }
-
- if (list == NULL) {
- fprintf (stderr, "forwardnews: out of memory!");
- ulog (-1, "Can't allocate ForwardList: Out of memory");
- return NULL;
- }
-
- if (base) {
- list->aliasFlag = 1;
- return base;
- }
-
- return list;
- }
-
- static FwdPat *
- NewPattern (const char *s)
- {
- FwdPat
- *pNode;
-
- if (!(pNode = calloc (sizeof (struct FwdPat), 1)) ||
- !(pNode->pattern = DupString (s))) {
-
- fprintf (stderr, "NewPattern: no memory!\n");
- ulog (-1, "NewPattern: no memory!");
- return NULL;
- }
-
- return pNode;
- }
-
- static char *
- NextPattern (char *in, char *out, int *length)
- {
- char
- c,
- *s1 = out;
-
- if (*in == ',')
- ++in;
- while (iswhite (*in))
- ++in;
-
- *length = 0;
- while (c = *in) {
- if (c == '\\' || c == ',' || c == '\n')
- break;
-
- ++in; /* Advance beyond current char. */
- if (!iswhite (c)) {
- *s1++ = c;
- ++*length;
- }
- }
- *s1 = '\0'; /* Terminate with a NULL. */
-
- return in;
- }
-
- void
- ParseSystem (FILE *sysFile, char *firstLine, ForwardList *system)
- {
- int
- length,
- patternLength;
- char
- pattern [80];
- FwdPat
- *pNode;
- char
- *s1,
- *theLine = firstLine;
-
- do {
- s1 = theLine;
- while (*s1 == ' ' || *s1 == '\t')
- s1++;
-
- if (*s1 == '\n' || *s1 == '#') {
- length = 0;
- }
- else {
- length = strlen (s1);
- if (s1 [length - 1] == '\n') {
- /* Delete trailing newline. */
- s1 [--length] = '\0';
- }
- }
-
- if (length > 0) {
- do {
- s1 = NextPattern (s1, pattern, &patternLength);
- if (patternLength) {
- D (("ParseSystem - next pattern: '%s'\n", pattern));
- pNode = NewPattern (pattern);
- if (pNode == NULL) {
- ulog (-1, "NewPattern failed");
- return;
- }
-
- /* Add this to our forward-linked list. */
- if (system->firstPattern == NULL)
- system->firstPattern = pNode;
- else
- system->lastPattern->nextPattern = pNode;
- system->lastPattern = pNode;
- }
- } while (*s1 == ',');
-
- if (*s1 != '\\')
- break;
- }
-
- theLine = inString;
- } while (fgets (inString, sizeof (inString), sysFile));
-
- return;
- }
-
-
- /* FUNCTION
- wildcmp - compare a wild card name with a normal name.
-
- SYNOPSIS
- int wildcmp(const char *wild, const char *name);
-
- DESCRIPTION
- Argument <wild>, a string containing wild card characters, is
- compared against <name>, a string containing no wild card
- characters. If the strings match, a one (1) is returned.
- Otherwise, a zero (0) is returned.
-
- AUTHOR
- Matt Dillon
- */
-
- #define MAXB 8
-
- int
- wildcmp (const char *wild, const char *name)
- {
- register char
- *w = wild;
- register char
- *n = name;
- char
- *back [MAXB] [2];
- register char
- s1, s2;
- int
- bi = 0;
-
- while (*n || *w){
- switch (*w) {
- case '*':
- if (bi == MAXB) {
- D (("Too many levels of '*'\n"));
- return 0;
- }
- back[bi][0]= w;
- back[bi][1]= n;
- ++bi;
- ++w;
- continue;
- goback:
- --bi;
- while (bi >= 0 && *back[bi][1] == '\0')
- --bi;
- if (bi < 0)
- return 0;
- w = back[bi][0] + 1;
- n = ++back[bi][1];
- ++bi;
- continue;
- case '?':
- if (!*n){
- if (bi)
- goto goback;
- return 0;
- }
- break;
- default:
- s1 = (*n >= 'A' && *n <= 'Z') ? *n - 'A' + 'a' : *n;
- s2 = (*w >= 'A' && *w <= 'Z') ? *w - 'A' + 'a' : *w;
- if (s1 != s2){
- if (bi)
- goto goback;
- return 0;
- }
- break;
- }
- if (*n)
- ++n;
- if (*w)
- ++w;
- }
-
- return 1;
- }
-