home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 1 / GoldFishApril1994_CD2.img / d4xx / d473 / cnewssrc / cnews_src.lzh / relay / sys.c < prev    next >
C/C++ Source or Header  |  1990-12-22  |  9KB  |  350 lines

  1. /* :ts=4
  2.  * news sys file reading functions
  3.  *
  4.  *    $Log$
  5.  */
  6.  
  7. #include <errno.h>
  8. #include "fixerrno.h"
  9. #include <stdio.h>
  10. #include <ctype.h>
  11. #ifdef unix
  12. # include <sys/types.h>
  13. # include <sys/stat.h>
  14. #endif /* unix */
  15. #include "libc.h"
  16. #include "fgetmfs.h"
  17. #include "news.h"
  18. #include "config.h"
  19. #include "system.h"
  20.  
  21. #define BTCHDIR "out.going/"        /* prefix of relative batch file name */
  22. #define BTCHPFX BTCHDIR                /* prefix of default batch file name */
  23. #define BTCHSFX "/togo"                /* suffix of same */
  24. #define CMDPFX "uux - -r -z "        /* prefix of default command */
  25. #define CMDSFX "!rnews"                /* suffix of same */
  26.  
  27. /* private */
  28. static FILE *fp = NULL;                /* stream for ctlfile(filerelname) */
  29. static char filerelname[] = "sys";    /* filename relative to $NEWSCTL */
  30.  
  31. /* forward decls */
  32. FORWARD char *parsecolon(), *reparse();
  33. FORWARD void readsys(), parsesysln(), parse(), parseflags(), newartfile();
  34. FORWARD int spacein();
  35.  
  36. /* exports */
  37. struct system *firstsys = NULL;    /* cache: 1st sys of in-core sys file */
  38. struct system *currsys = NULL;    /* current system */
  39.  
  40. /* imports */
  41. extern boolean donesys();
  42. extern struct system *mysysincache();
  43. extern void rewsys(), remmysys(), advcurrsys(), setupsys();
  44.  
  45. struct system *
  46. oursys()            /* return our sys entry */
  47. {
  48.     register struct system *sys = mysysincache();
  49.     static struct system fakesys;
  50.  
  51.     if (sys == NULL) {
  52.         rewsys(fp);
  53.         while ((sys = nextsys()) != NULL && !STREQ(sys->sy_name, hostname()))
  54.             ;
  55.         if (sys == NULL) {
  56.             /* no entry: cook one up; no need to malloc members */
  57.             fakesys.sy_name = hostname();
  58.             fakesys.sy_excl = NULL;
  59.             fakesys.sy_ngs = "all";
  60.             fakesys.sy_distr = "all";
  61.             fakesys.sy_flags = 0;
  62.             fakesys.sy_lochops = 0;
  63.             fakesys.sy_cmd = "";
  64.             fakesys.sy_next = NULL;
  65.             sys = &fakesys;
  66.         }
  67.         remmysys(sys);            /* for future reference */
  68.     }
  69.     return sys;
  70. }
  71.  
  72. /*
  73.  * Return the next sys entry, which may span multiple lines.
  74.  * Returned pointer points at a struct whose lifetime (and that of its
  75.  * members) is not promised to last beyond the next call to nextsys();
  76.  * copy it and its pointed-to strings if you need them for longer.
  77.  *
  78.  * Note that readsys() reads one entry on small systems, but the entire
  79.  * sys file on big systems, so the common code in this file is subtle.
  80.  */
  81. struct system *
  82. nextsys()
  83. {
  84.     struct system *retsys;
  85.  
  86.     if (firstsys == NULL && fp == NULL)
  87.         if ((fp = fopenwclex(ctlfile(filerelname), "r")) == NULL)
  88.             return NULL;
  89.     if (fp != NULL && firstsys == NULL)
  90.         readsys();
  91.     retsys = currsys;
  92.     advcurrsys();
  93.     return retsys;
  94. }
  95.  
  96. /*
  97.  * On small systems, read one entry; else read whole sys file (done once only).
  98.  * Ignores '#' comments and blank lines; uses cfgetms to read possibly-
  99.  * continued lines of arbitrary length.
  100.  */
  101. STATIC void
  102. readsys()
  103. {
  104.     register char *sysline;
  105.  
  106.     setupsys(fp);        /* reuse currsys or rewind sys file */
  107.     while ((sysline = cfgetms(fp)) != NULL) {
  108.         if (sysline[0] != '#' && sysline[0] != '\n')
  109.             parsesysln(sysline);
  110.         free(sysline);
  111.         if (donesys())        /* early exit if on disk (small) */
  112.             return;
  113.     }
  114.     (void) nfclose(fp);
  115.     fp = NULL;
  116.     rewsys(fp);
  117. }
  118.  
  119. static char *curr, *next;            /* parsing state */
  120.  
  121. /*
  122.  * Parse (and modify) sysline into *currsys, which is malloced here
  123.  * and freed iff on a small system, in readsys(), see freecursys().
  124.  *
  125.  * Side-effect: sysline has a trailing newline removed.
  126.  */
  127. STATIC void
  128. parsesysln(sysline)
  129. register char *sysline;
  130. {
  131.     register struct system *sysp =(struct system *)nemalloc(sizeof *sysp);
  132.     char *flagstring;
  133.  
  134.     trim(sysline);
  135.     next = sysline;
  136.     parse(&sysp->sy_name);
  137.     parse(&sysp->sy_ngs);
  138.     parse(&flagstring);
  139.     parse(&sysp->sy_cmd);
  140.     errno = 0;
  141.     if (spacein(sysp->sy_name))
  142.         errunlock(
  143.         "whitespace in system name (or exclusions) of sys entry for `%s'",
  144.             sysp->sy_name);
  145.     if (spacein(sysp->sy_ngs))
  146.         errunlock(
  147.         "whitespace in newsgroups (or distributions) of sys entry for `%s'",
  148.             sysp->sy_name);
  149.     if (spacein(flagstring))
  150.         errunlock("whitespace in flags of sys entry for `%s'",
  151.             sysp->sy_name);
  152.     /* could check for extra fields here */
  153.  
  154.     parseflags(flagstring, sysp);
  155.     free(flagstring);        /* malloced by parse */
  156.     sysp->sy_next = NULL;
  157.  
  158.     /* reparse for embedded slashes */
  159.     sysp->sy_excl = reparse(sysp->sy_name, '/');
  160.     sysp->sy_distr = reparse(sysp->sy_ngs, '/');
  161.     if (sysp->sy_distr == NULL)    /* default distr is ngs... */
  162.         sysp->sy_distr = sysp->sy_ngs;
  163.  
  164.     sysdeflt(sysp);            /* fill in any defaults */
  165.  
  166.     /* stash *sysp away on the tail of the current list of systems */
  167.     *(firstsys == NULL? &firstsys: &currsys->sy_next) = sysp;
  168.     currsys = sysp;
  169. }
  170.  
  171. STATIC int
  172. spacein(s)
  173. register char *s;
  174. {
  175.     return strchr(s, ' ') != NULL || strchr(s, '\t') != NULL;
  176. }
  177.  
  178. /*
  179.  * fill in defaults in sysp.
  180.  *
  181.  * expand a name of "ME" to hostname().
  182.  * If an empty batch file name was given, supply a default
  183.  * ($NEWSARTS/BTCHPFX system BTCHSFX).
  184.  * Prepend $NEWSARTS/BTCHDIR to relative file names.
  185.  * If an empty command was given, supply a default (uux - -r -z system!rnews).
  186.  * (This *is* yucky and uucp-version-dependent.)
  187.  */
  188. void
  189. sysdeflt(sysp)
  190. register struct system *sysp;
  191. {
  192.     if (STREQ(sysp->sy_name, "ME")) {
  193.         free(sysp->sy_name);    /* malloced by parse */
  194.         sysp->sy_name = strsave(hostname());
  195.     }
  196.     if (sysp->sy_flags&FLG_BATCH && sysp->sy_cmd[0] == '\0') {
  197.         register char *deffile = nemalloc((unsigned) strlen(BTCHPFX) +
  198.             strlen(sysp->sy_name) + strlen(BTCHSFX) + SIZENUL);
  199.  
  200.         (void) strcpy(deffile, BTCHPFX);
  201.         (void) strcat(deffile, sysp->sy_name);
  202.         (void) strcat(deffile, BTCHSFX);
  203.         /* frees old sysp->sy_cmd, deffile */
  204.         newartfile(sysp, deffile);
  205.     }
  206. #ifdef unix
  207.     else if (sysp->sy_flags&FLG_BATCH && sysp->sy_cmd[0] != FNDELIM)
  208. #elif defined(AMIGA)
  209.     else if (sysp->sy_flags&FLG_BATCH && !strchr(sysp->sy_cmd, ':'))
  210. #endif
  211.     {
  212.         register char *absfile = nemalloc((unsigned) strlen(BTCHDIR) +
  213.             strlen(sysp->sy_cmd) + SIZENUL);
  214.  
  215.         (void) strcpy(absfile, BTCHDIR);
  216.         (void) strcat(absfile, sysp->sy_cmd);
  217.         /* frees old sysp->sy_cmd, absfile */
  218.         newartfile(sysp, absfile);
  219.     } else if (!(sysp->sy_flags&FLG_BATCH) && sysp->sy_cmd[0] == '\0') {
  220.         free(sysp->sy_cmd);    /* malloced by parse */
  221.         sysp->sy_cmd = nemalloc((unsigned) STRLEN(CMDPFX) +
  222.             strlen(sysp->sy_name) + STRLEN(CMDSFX) + SIZENUL);
  223.         (void) strcpy(sysp->sy_cmd, CMDPFX);
  224.         (void) strcat(sysp->sy_cmd, sysp->sy_name);
  225.         (void) strcat(sysp->sy_cmd, CMDSFX);
  226.     }
  227. }
  228.  
  229. STATIC void
  230. newartfile(sysp, file)        /* replace sysp->sy_cmd with artfile(file) */
  231. register struct system *sysp;
  232. register char *file;
  233. {
  234.     free(sysp->sy_cmd);        /* malloced by parse */
  235.     sysp->sy_cmd = strsave(artfile(file));
  236.     free(file);
  237. }
  238.  
  239. /*
  240.  * Parse "next" to colon into malloced storage, return its ptr via "into".
  241.  * *into is freed iff on a small system, in readsys(), see freecursys().
  242.  */
  243. STATIC void
  244. parse(into)
  245. register char **into;
  246. {
  247.     curr = next;
  248.     if (curr == NULL)
  249.         *into = strsave("");
  250.     else {
  251.         next = parsecolon(curr);
  252.         *into = strsave(curr);
  253.     }
  254. }
  255.  
  256. STATIC char *
  257. parsecolon(line)        /* return NULL or ptr. to byte after colon */
  258. char *line;
  259. {
  260.     register char *colon;
  261.  
  262.     STRCHR(line, ':', colon);
  263.     if (colon != NULL)
  264.         *colon++ = '\0';
  265.     return colon;
  266. }
  267.  
  268. /*
  269.  * replace "delim" in "field" with a NUL and return the address of the byte
  270.  * after the NUL (the address of the second subfield), or NULL if no
  271.  * "delim" was present.
  272.  */
  273. STATIC char *
  274. reparse(field, delim)
  275. char *field;
  276. int delim;
  277. {
  278.     register char *delimp = strchr(field, delim);
  279.  
  280.     if (delimp != NULL)
  281.         *delimp++ = '\0';
  282.     return delimp;
  283. }
  284.  
  285. /*
  286.  * Parse sys file flags into sysp.
  287.  */
  288. STATIC void
  289. parseflags(flags, sysp)
  290. register char *flags;
  291. register struct system *sysp;
  292. {
  293.     sysp->sy_flags = 0;
  294.     sysp->sy_lochops = 0;        /* default L value */
  295.     errno = 0;
  296.     for (; *flags != '\0'; flags++)
  297.         switch (*flags) {
  298.         case 'A':
  299.             errunlock("A news format not supported", "");
  300.             /* NOTREACHED */
  301.         case 'B':        /* mostly harmless */
  302.             break;
  303.         case 'f':
  304.             sysp->sy_flags |= FLG_BATCH|FLG_SZBATCH;
  305.             break;
  306.         case 'F':
  307.             sysp->sy_flags |= FLG_BATCH;
  308.             break;
  309.         case 'I':        /* NNTP hook: write msgids, !files */
  310.             sysp->sy_flags |= FLG_BATCH|FLG_IHAVE;
  311.             break;
  312.         case 'L':        /* Ln */
  313.             sysp->sy_flags |= FLG_LOCAL;
  314.             sysp->sy_lochops = 0;
  315.             while (isascii(flags[1]) && isdigit(flags[1])) {
  316.                 sysp->sy_lochops *= 10;
  317.                 sysp->sy_lochops += *++flags - '0';
  318.             }
  319.             break;
  320.         case 'm':        /* send only moderated groups */
  321.             sysp->sy_flags |= FLG_MOD;
  322.             break;
  323.         case 'N':
  324.             errunlock(
  325.     "The N flag is a wasteful old kludge; see the I flag instead.", "");
  326.             /* NOTREACHED */
  327.         case 'n':        /* NNTP hook: write files+msgids */
  328.             sysp->sy_flags |= FLG_BATCH|FLG_NBATCH;
  329.             break;
  330.         case 'u':        /* send only unmoderated groups */
  331.             sysp->sy_flags |= FLG_UNMOD;
  332.             break;
  333.         case 'U':        /* mostly harmless */
  334.             break;
  335.         case 'H':        /* bugger off */
  336.         case 'S':        /* bugger off */
  337.         case 'M':        /* multicast: obs., see batcher */
  338.         case 'O':        /* multicast: obs., see batcher */
  339.         default:
  340.             errunlock("unknown sys flag `%s' given", flags);
  341.             /* NOTREACHED */
  342.         }
  343. }
  344.  
  345. void
  346. rewndsys()
  347. {
  348.     rewsys(fp);
  349. }
  350.