home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD2.img
/
d4xx
/
d473
/
cnewssrc
/
cnews_src.lzh
/
relay
/
sys.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-12-22
|
9KB
|
350 lines
/* :ts=4
* news sys file reading functions
*
* $Log$
*/
#include <errno.h>
#include "fixerrno.h"
#include <stdio.h>
#include <ctype.h>
#ifdef unix
# include <sys/types.h>
# include <sys/stat.h>
#endif /* unix */
#include "libc.h"
#include "fgetmfs.h"
#include "news.h"
#include "config.h"
#include "system.h"
#define BTCHDIR "out.going/" /* prefix of relative batch file name */
#define BTCHPFX BTCHDIR /* prefix of default batch file name */
#define BTCHSFX "/togo" /* suffix of same */
#define CMDPFX "uux - -r -z " /* prefix of default command */
#define CMDSFX "!rnews" /* suffix of same */
/* private */
static FILE *fp = NULL; /* stream for ctlfile(filerelname) */
static char filerelname[] = "sys"; /* filename relative to $NEWSCTL */
/* forward decls */
FORWARD char *parsecolon(), *reparse();
FORWARD void readsys(), parsesysln(), parse(), parseflags(), newartfile();
FORWARD int spacein();
/* exports */
struct system *firstsys = NULL; /* cache: 1st sys of in-core sys file */
struct system *currsys = NULL; /* current system */
/* imports */
extern boolean donesys();
extern struct system *mysysincache();
extern void rewsys(), remmysys(), advcurrsys(), setupsys();
struct system *
oursys() /* return our sys entry */
{
register struct system *sys = mysysincache();
static struct system fakesys;
if (sys == NULL) {
rewsys(fp);
while ((sys = nextsys()) != NULL && !STREQ(sys->sy_name, hostname()))
;
if (sys == NULL) {
/* no entry: cook one up; no need to malloc members */
fakesys.sy_name = hostname();
fakesys.sy_excl = NULL;
fakesys.sy_ngs = "all";
fakesys.sy_distr = "all";
fakesys.sy_flags = 0;
fakesys.sy_lochops = 0;
fakesys.sy_cmd = "";
fakesys.sy_next = NULL;
sys = &fakesys;
}
remmysys(sys); /* for future reference */
}
return sys;
}
/*
* Return the next sys entry, which may span multiple lines.
* Returned pointer points at a struct whose lifetime (and that of its
* members) is not promised to last beyond the next call to nextsys();
* copy it and its pointed-to strings if you need them for longer.
*
* Note that readsys() reads one entry on small systems, but the entire
* sys file on big systems, so the common code in this file is subtle.
*/
struct system *
nextsys()
{
struct system *retsys;
if (firstsys == NULL && fp == NULL)
if ((fp = fopenwclex(ctlfile(filerelname), "r")) == NULL)
return NULL;
if (fp != NULL && firstsys == NULL)
readsys();
retsys = currsys;
advcurrsys();
return retsys;
}
/*
* On small systems, read one entry; else read whole sys file (done once only).
* Ignores '#' comments and blank lines; uses cfgetms to read possibly-
* continued lines of arbitrary length.
*/
STATIC void
readsys()
{
register char *sysline;
setupsys(fp); /* reuse currsys or rewind sys file */
while ((sysline = cfgetms(fp)) != NULL) {
if (sysline[0] != '#' && sysline[0] != '\n')
parsesysln(sysline);
free(sysline);
if (donesys()) /* early exit if on disk (small) */
return;
}
(void) nfclose(fp);
fp = NULL;
rewsys(fp);
}
static char *curr, *next; /* parsing state */
/*
* Parse (and modify) sysline into *currsys, which is malloced here
* and freed iff on a small system, in readsys(), see freecursys().
*
* Side-effect: sysline has a trailing newline removed.
*/
STATIC void
parsesysln(sysline)
register char *sysline;
{
register struct system *sysp =(struct system *)nemalloc(sizeof *sysp);
char *flagstring;
trim(sysline);
next = sysline;
parse(&sysp->sy_name);
parse(&sysp->sy_ngs);
parse(&flagstring);
parse(&sysp->sy_cmd);
errno = 0;
if (spacein(sysp->sy_name))
errunlock(
"whitespace in system name (or exclusions) of sys entry for `%s'",
sysp->sy_name);
if (spacein(sysp->sy_ngs))
errunlock(
"whitespace in newsgroups (or distributions) of sys entry for `%s'",
sysp->sy_name);
if (spacein(flagstring))
errunlock("whitespace in flags of sys entry for `%s'",
sysp->sy_name);
/* could check for extra fields here */
parseflags(flagstring, sysp);
free(flagstring); /* malloced by parse */
sysp->sy_next = NULL;
/* reparse for embedded slashes */
sysp->sy_excl = reparse(sysp->sy_name, '/');
sysp->sy_distr = reparse(sysp->sy_ngs, '/');
if (sysp->sy_distr == NULL) /* default distr is ngs... */
sysp->sy_distr = sysp->sy_ngs;
sysdeflt(sysp); /* fill in any defaults */
/* stash *sysp away on the tail of the current list of systems */
*(firstsys == NULL? &firstsys: &currsys->sy_next) = sysp;
currsys = sysp;
}
STATIC int
spacein(s)
register char *s;
{
return strchr(s, ' ') != NULL || strchr(s, '\t') != NULL;
}
/*
* fill in defaults in sysp.
*
* expand a name of "ME" to hostname().
* If an empty batch file name was given, supply a default
* ($NEWSARTS/BTCHPFX system BTCHSFX).
* Prepend $NEWSARTS/BTCHDIR to relative file names.
* If an empty command was given, supply a default (uux - -r -z system!rnews).
* (This *is* yucky and uucp-version-dependent.)
*/
void
sysdeflt(sysp)
register struct system *sysp;
{
if (STREQ(sysp->sy_name, "ME")) {
free(sysp->sy_name); /* malloced by parse */
sysp->sy_name = strsave(hostname());
}
if (sysp->sy_flags&FLG_BATCH && sysp->sy_cmd[0] == '\0') {
register char *deffile = nemalloc((unsigned) strlen(BTCHPFX) +
strlen(sysp->sy_name) + strlen(BTCHSFX) + SIZENUL);
(void) strcpy(deffile, BTCHPFX);
(void) strcat(deffile, sysp->sy_name);
(void) strcat(deffile, BTCHSFX);
/* frees old sysp->sy_cmd, deffile */
newartfile(sysp, deffile);
}
#ifdef unix
else if (sysp->sy_flags&FLG_BATCH && sysp->sy_cmd[0] != FNDELIM)
#elif defined(AMIGA)
else if (sysp->sy_flags&FLG_BATCH && !strchr(sysp->sy_cmd, ':'))
#endif
{
register char *absfile = nemalloc((unsigned) strlen(BTCHDIR) +
strlen(sysp->sy_cmd) + SIZENUL);
(void) strcpy(absfile, BTCHDIR);
(void) strcat(absfile, sysp->sy_cmd);
/* frees old sysp->sy_cmd, absfile */
newartfile(sysp, absfile);
} else if (!(sysp->sy_flags&FLG_BATCH) && sysp->sy_cmd[0] == '\0') {
free(sysp->sy_cmd); /* malloced by parse */
sysp->sy_cmd = nemalloc((unsigned) STRLEN(CMDPFX) +
strlen(sysp->sy_name) + STRLEN(CMDSFX) + SIZENUL);
(void) strcpy(sysp->sy_cmd, CMDPFX);
(void) strcat(sysp->sy_cmd, sysp->sy_name);
(void) strcat(sysp->sy_cmd, CMDSFX);
}
}
STATIC void
newartfile(sysp, file) /* replace sysp->sy_cmd with artfile(file) */
register struct system *sysp;
register char *file;
{
free(sysp->sy_cmd); /* malloced by parse */
sysp->sy_cmd = strsave(artfile(file));
free(file);
}
/*
* Parse "next" to colon into malloced storage, return its ptr via "into".
* *into is freed iff on a small system, in readsys(), see freecursys().
*/
STATIC void
parse(into)
register char **into;
{
curr = next;
if (curr == NULL)
*into = strsave("");
else {
next = parsecolon(curr);
*into = strsave(curr);
}
}
STATIC char *
parsecolon(line) /* return NULL or ptr. to byte after colon */
char *line;
{
register char *colon;
STRCHR(line, ':', colon);
if (colon != NULL)
*colon++ = '\0';
return colon;
}
/*
* replace "delim" in "field" with a NUL and return the address of the byte
* after the NUL (the address of the second subfield), or NULL if no
* "delim" was present.
*/
STATIC char *
reparse(field, delim)
char *field;
int delim;
{
register char *delimp = strchr(field, delim);
if (delimp != NULL)
*delimp++ = '\0';
return delimp;
}
/*
* Parse sys file flags into sysp.
*/
STATIC void
parseflags(flags, sysp)
register char *flags;
register struct system *sysp;
{
sysp->sy_flags = 0;
sysp->sy_lochops = 0; /* default L value */
errno = 0;
for (; *flags != '\0'; flags++)
switch (*flags) {
case 'A':
errunlock("A news format not supported", "");
/* NOTREACHED */
case 'B': /* mostly harmless */
break;
case 'f':
sysp->sy_flags |= FLG_BATCH|FLG_SZBATCH;
break;
case 'F':
sysp->sy_flags |= FLG_BATCH;
break;
case 'I': /* NNTP hook: write msgids, !files */
sysp->sy_flags |= FLG_BATCH|FLG_IHAVE;
break;
case 'L': /* Ln */
sysp->sy_flags |= FLG_LOCAL;
sysp->sy_lochops = 0;
while (isascii(flags[1]) && isdigit(flags[1])) {
sysp->sy_lochops *= 10;
sysp->sy_lochops += *++flags - '0';
}
break;
case 'm': /* send only moderated groups */
sysp->sy_flags |= FLG_MOD;
break;
case 'N':
errunlock(
"The N flag is a wasteful old kludge; see the I flag instead.", "");
/* NOTREACHED */
case 'n': /* NNTP hook: write files+msgids */
sysp->sy_flags |= FLG_BATCH|FLG_NBATCH;
break;
case 'u': /* send only unmoderated groups */
sysp->sy_flags |= FLG_UNMOD;
break;
case 'U': /* mostly harmless */
break;
case 'H': /* bugger off */
case 'S': /* bugger off */
case 'M': /* multicast: obs., see batcher */
case 'O': /* multicast: obs., see batcher */
default:
errunlock("unknown sys flag `%s' given", flags);
/* NOTREACHED */
}
}
void
rewndsys()
{
rewsys(fp);
}