Subject: v12i031: C News alpha release, Part06/14 Newsgroups: comp.sources.unix Sender: sources Approved: rs@uunet.UU.NET Submitted-by: utzoo!henry (Henry Spencer) Posting-number: Volume 12, Issue 31 Archive-name: cnews/part06 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'batch/sendbatches' <<'END_OF_FILE' X# Master batching control. XNEWSBIN=${NEWSBIN-/usr/lib/newsbin} XNEWSCTL=${NEWSCTL-/usr/lib/news} XNEWSARTS=${NEWSARTS-/usr/spool/news} XPATH=$NEWSCTL/batch:$NEWSBIN/batch:/bin:/usr/bin ; export PATH Xorigpath=$PATH XNEWSUMASK=${NEWSUMASK-002} Xumask $NEWSUMASK X X# Locking. Xcd $NEWSCTL Xecho $$ >LOCKbatch$$ Xif ln LOCKbatch$$ LOCKbatch >/dev/null 2>/dev/null Xthen X rm LOCKbatch$$ X trap "rm -f $NEWSCTL/LOCKbatch ; exit" 0 1 2 3 15 Xelse X rm LOCKbatch$$ X exit 0 Xfi X X# Go to the heart of the matter. Xcd $NEWSCTL/batch X X# Determine what systems are being requested, in what order. Xcase $# Xin X 0) X ls | sed -n '/^b\./s///p' | sort >/tmp/nb$$sy X if test -r sites X then X egrep -v '^[ ]*(#|$)' sites | awk '{ print $1, NR }' | X sort >/tmp/nb$$o X join -a1 -e 9999 -o 1.1 2.2 /tmp/nb$$sy /tmp/nb$$o >/tmp/nb$$t X sort +1 -n /tmp/nb$$t | awk '{ print $1 }' >/tmp/nb$$sy X fi X syses=`cat /tmp/nb$$sy` X rm -f /tmp/nb$$sy /tmp/nb$$o /tmp/nb$$t X ;; X X *) X case "$1" X in X -c) X if test ! -r sites X then X echo "$0: -c illegal in absence of sites file" >&2 X exit 2 X fi X shift X syses=`for class in $* X do X egrep -v '^[ ]*(#|$)' sites | X egrep "[, ]$class(\$|[, ])" | X awk '{print $1}' X done` X ;; X X *) X syses="$*" X ;; X esac X ;; Xesac X X# Start up logging. Xmv $NEWSCTL/batchlog.o $NEWSCTL/batchlog.oo Xmv $NEWSCTL/batchlog $NEWSCTL/batchlog.o Xdate >$NEWSCTL/batchlog X X# Run through them. Xfor sys in $syses Xdo X # Move into his directory, include it in search path. X here=$NEWSCTL/batch/b.$sys X if test ! -d $here X then X echo "$0: cannot find batch directory for site $sys" >&2 X continue X fi X cd $here X PATH=$here:$origpath ; export PATH X NEWSSITE=$sys ; export NEWSSITE # For site-specific programs. X X # Is there anything to do? X files=`echo togo*` X if test "$files" = 'togo*' || test "$files" = "togo" -a ! -s togo X then X continue # no X fi X X # How many batches should we send? X outstand=`queuelen $sys` X limit=`queuemax` X nbatch=`expr $limit - $outstand` X batchsize=`batchsize` X roomfor=`roomfor $batchsize` X if test " $nbatch" -gt " $roomfor" X then X nbatch=$roomfor X fi X X # If not allowed to send, remember reason. X status='batches flowing' X if test " $nbatch" -le 0 X then X if test " $roomfor" -le 0 X then X status='disk too full for batching' X else X status='queue full' X fi X fi X X # Try sending some. X while test " $nbatch" -gt 0 X do X # Does he have batches prepared already? X if test "`echo togo.*`" = 'togo.*' X then X # No -- need some more batches. X if test ! -s togo X then X break # Nothing left to do. X fi X batchprep $batchsize X fi X X # Send some batches. X them=`ls | egrep '^togo\.' | sed "${nbatch}q"` X for f in $them X do X batchmake -d $NEWSARTS $f | batchmunch | X batchxmit $sys X rm $f X done X ndone=`echo $them | wc -w` X nbatch=`expr $nbatch - $ndone` X X # Recheck the space -- it can fall for other reasons. X roomfor=`roomfor $batchsize` X if test " $nbatch" -gt " $roomfor" X then X nbatch=$roomfor X fi X done X X # Report status, if appropriate. X nart=`cat togo* | wc -l | awk '{print $1}'` X if test " $nart" -gt 0 X then X echo "$sys backlog $nart ($status)" >>$NEWSCTL/batchlog X fi Xdone END_OF_FILE if test 3153 -ne `wc -c <'batch/sendbatches'`; then echo shar: \"'batch/sendbatches'\" unpacked with wrong size! fi # end of 'batch/sendbatches' fi if test -f 'expire/expire.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'expire/expire.1'\" else echo shar: Extracting \"'expire/expire.1'\" \(3912 characters\) sed "s/^X//" >'expire/expire.1' <<'END_OF_FILE' X.TH EXPIRE 1M local X.DA 3 Oct 1987 X.SH NAME Xexpire \- expire old news X.SH SYNOPSIS X.B /usr/lib/newsbin/expire/expire X[ X.B \-a Xarchdir X] [ X.B \-p X] [ X.B \-o X] X[ controlfile ] X.SH DESCRIPTION X.I Expire Xexpires old news, removing it from the current-news directories and X(if asked to) archiving it elsewhere. XIt updates news's X.I history Xfile to match. X.I Expire Xshould be run nightly. X.PP X.IR Expire 's Xoperations are controlled by a control file X(which can be named or supplied on standard input), Xwhich is not optional\(emthere is no default behavior. XEach line of the control file should have four white-space-separated Xfields, as follows. X.PP XThe first field is one or more newsgroups, Xseparated by commas (no spaces!); Xpartial specifications are acceptable (e.g. `comp' specifies all groups Xwith that prefix). X.PP XThe second field is one letter, `m', `u', or `x', specifying that the line Xapplies only to moderated groups, only to unmoderated groups, or to both, Xrespectively. X.PP XThe third field specifies the expiry period in days. XThe most general form is three numbers separated by dashes. XThe units are days; decimal fractions are permitted. XThe first number gives the retention period: Xhow long must pass after an article's arrival before it is a candidate Xfor expiry. XThe third number gives the purge date: Xhow long must pass after arrival Xbefore the article will be expired unconditionally. XThe middle number gives the default expiry date: Xhow long after an article's arrival it is expired by default. XAn explicit expiry date in the article will override the default expiry Xdate but not the retention period or the purge date. XIf the field contains only two numbers with a dash separating them, Xthe retention period defaults to 0. XIf the field contains only a number, the retention period defaults to 0 Xand the purge date defaults to `never'. X.PP XThe fourth field is an archiving directory, Xor `@' which indicates that the default archiving directory (see \fB\-a\fR) Xshould be used, Xor `\-' which suppresses archiving. X.PP XThe first line of the control file which applies to a given article is Xused to control its expiry. XIt is an error for no line to apply; Xthe last line should be something like `all\ x\ 14\ \-' Xto ensure that at least one line is always applicable. XCross-posted articles are treated as if they were independently posted Xto each group. X.PP XThe X.B \-a Xoption specifies a default archiving directory; Xif no default is given, it is illegal for the control file to contain Xany `@' archive-directory fields. X.PP X.I Expire Xcreates subdirectories under an archiving directory automatically, Xbut will not create the archiving directory itself. XArchiving directories must be given as full pathnames. X.PP XThe X.B \-p Xoption causes an `index' line to be printed for each archived article, Xcontaining its pathname, message ID, date received, and `Subject:' line. XThe X.B \-o Xoption tells X.I expire Xto use the obsolete 4-field history-file format used by early variants Xof C news. X.PP X\fIExpire\fR and its auxiliaries recognize the standard Xenvironment variables \fB$\&NEWSARTS\fR, X\fB$\&NEWSCTL\fR, \fB$\&NEWSBIN\fR, and \fB$NEWSUMASK\fR Xwhich indicate, respectively, non-default locations Xfor news articles, news control files, and news programs, Xand a non-default \fIumask\fR (see \fIumask\fR(2)) for file creation X(the default \fIumask\fR is 002). X.SH FILES X.ta 4c X.nf X\fIlibrary\fR/history history file X\fIlibrary\fR/history.pag \fIdbm\fR database for history file X\fIlibrary\fR/history.dir \fIdbm\fR database for history file X.SH SEE ALSO Xinews(1) X.SH HISTORY XWritten at U of Toronto by Henry Spencer, with contributions by Geoff Collyer. X.SH BUGS XArchiving is always done by copying, never by linking. XThis has the side effect that cross-posted articles are archived as Xseveral independent copies. X.PP XThe X.B \-p Xsubject-finder botches continued `Subject:' lines, although Xthese are rare. END_OF_FILE if test 3912 -ne `wc -c <'expire/expire.1'`; then echo shar: \"'expire/expire.1'\" unpacked with wrong size! fi # end of 'expire/expire.1' fi if test -f 'expire/ns.p' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'expire/ns.p'\" else echo shar: Extracting \"'expire/ns.p'\" \(3614 characters\) sed "s/^X//" >'expire/ns.p' <<'END_OF_FILE' Xmkdir ns ns/foo ns/bar ns/bletch Xmkdir ns/foo/one ns/foo/two ns/foo/three Xmkdir ns/bar/one ns/bar/two ns/bar/five Xmkdir ns/bletch/one ns/bletch/four ns/bletch/six X X# The "should-expire" headers are for checking afterward. X X# In foo/one, run through the simple cases of dates before and after X# expiry dates. Also where the Subject: line is in the article. Xoldfile 11 ns/foo/one/95 < XShould-expire: yes XSubject: foo one/95 X Xbody X! Xoldfile 10 ns/foo/one/96 < XShould-expire: no XSubject: foo one/96 X Xbody X! Xoldfile 11 ns/foo/one/97 < XShould-expire: yes XSubject: foo one/97 XExpires: `olddate 1` X Xbody X! Xoldfile 10 ns/foo/one/98 < XShould-expire: no XExpires: `olddate -1` X Xbody X! Xoldfile 11 ns/foo/one/99 < XShould-expire: no XExpires: `olddate -1` XSubject: foo one/99 XMumble: frotz X Xbody X! Xoldfile 10 ns/foo/one/100 < XShould-expire: yes XExpires: `olddate 1` X Xbody X! X X# bar/one just has a simple pair Xoldfile 11 ns/bar/one/99 < XShould-expire: yes XSubject: bar one/99 X Xbody X! Xoldfile 10 ns/bar/one/100 < XShould-expire: no XSubject: bar one/100 X Xbody X! X X# bletch/one just has a simple pair Xoldfile 11 ns/bletch/one/99 < XShould-expire: yes XSubject: bletch one/99 X Xbody X! Xoldfile 10 ns/bletch/one/100 < XShould-expire: no XSubject: bletch one/100 X Xbody X! X X# foo.two has a simple pair again Xoldfile 14 ns/foo/two/99 < XShould-expire: no XSubject: foo two/99 X Xbody X! Xoldfile 16 ns/foo/two/100 < XShould-expire: yes XSubject: foo two/100 X Xbody X! X X# bar.two, another simple pair Xoldfile 14 ns/bar/two/99 < XShould-expire: no XSubject: bar two/99 X Xbody X! Xoldfile 16 ns/bar/two/100 < XShould-expire: yes XSubject: bar two/100 X Xbody X! X X# foo.three adds a purge date Xoldfile 4 ns/foo/three/98 < XShould-expire: no XSubject: foo three/98 X Xbody X! Xoldfile 6 ns/foo/three/99 < XShould-expire: yes XSubject: foo three/99 X Xbody X! Xoldfile 16 ns/foo/three/100 < XShould-expire: yes XExpires: `olddate -1` XSubject: foo three/100 X Xbody X! X X# bletch.four has both a retain date and a purge date Xoldfile 9 ns/bletch/four/97 < XShould-expire: no XSubject: bletch four/97 X Xbody X! Xoldfile 11 ns/bletch/four/98 < XShould-expire: yes XSubject: bletch four/98 X Xbody X! Xoldfile 3 ns/bletch/four/99 < XShould-expire: no XExpires: `olddate 1` XSubject: bletch four/99 X Xbody X! Xoldfile 25 ns/bletch/four/100 < XShould-expire: yes XExpires: `olddate -1` XSubject: bletch four/100 X Xbody X! X X# bar.five gets the catchall at the end and is another simple pair. Xoldfile 31 ns/bar/five/99 < XShould-expire: yes XSubject: bar five/99 X Xbody X! Xoldfile 29 ns/bar/five/100 < XShould-expire: no XSubject: bar five/100 X Xbody X! X X# bletch.six is not in the active file, but is otherwise orthodox Xoldfile 31 ns/bletch/six/99 < XShould-expire: yes XSubject: bletch six/99 X Xbody X! Xoldfile 29 ns/bletch/six/100 < XShould-expire: no XSubject: bletch six/100 X Xbody X! END_OF_FILE if test 3614 -ne `wc -c <'expire/ns.p'`; then echo shar: \"'expire/ns.p'\" unpacked with wrong size! fi # end of 'expire/ns.p' fi if test -f 'expire/xargs.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'expire/xargs.c'\" else echo shar: Extracting \"'expire/xargs.c'\" \(3713 characters\) sed "s/^X//" >'expire/xargs.c' <<'END_OF_FILE' X/* X * xargs - gather up filenames from input and run command on them X */ X X#include X#include X X#define STREQ(a, b) (strcmp((a), (b)) == 0) X X#ifndef lint Xstatic char Sccsid[] = "@(#)xargs.c 1.2 of 6 May 86"; X#endif X Xchar argchars[NCARGS]; /* Characters of arguments. */ Xchar *argfree = argchars; /* First free char in argchars. */ Xchar *argbase = argchars; /* First char after constant args. */ X Xchar *argptrs[NCARGS/sizeof(char *)]; /* Pointers to arguments. */ Xint nargs = 0; /* Number of entries in argptrs. */ Xint base = 0; /* Number of constant entries. */ X Xint size = 0; /* Size of total argument bundle so far. */ Xint basesize = 0; /* Size of constant args. */ X#ifndef XARGMAX X#define XARGMAX (NCARGS - 50) /* 50 is misc. overhead plus safety margin. */ X#endif X X#ifndef OKSTAT X#define OKSTAT 1 /* Highest exit status considered normal. */ X#endif X Xextern char **environ; X Xchar *progname; Xextern char *mkprogname(); X X/* X * main - parse arguments, handle options, main control X */ Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X int c; X int errflg = 0; X char *cmd; X register char **envp; X char buf[BUFSIZ]; X register int len; X int maxstat = 0; X int thisstat; X extern int optind; X extern char *optarg; X X progname = mkprogname(argv[0]); X X while ((c = getopt(argc, argv, "")) != EOF) X switch (c) { X case '?': X default: X errflg++; X break; X } X if (errflg || optind == argc) { X fprintf(stderr, "Usage: %s command [arg] ...\n", progname); X exit(2); X } X X /* Plug in the constant arguments. */ X cmd = argv[optind]; X for (; optind < argc; optind++) { X argptrs[nargs++] = argv[optind]; X size += strlen(argv[optind]) + 1 + sizeof(char *); X } X X /* Add in the size of the environment. */ X for (envp = environ; *envp != NULL; envp++) X size += strlen(*envp) + 1 + sizeof(char *); X X /* Establish base. */ X argbase = argfree; X base = nargs; X basesize = size; X if (basesize >= XARGMAX) { X fprintf(stderr, "%s: command too big\n", progname); X exit(2); X } X X /* And do it. */ X while (fgets(buf, (int)sizeof(buf), stdin) != NULL) { X len = strlen(buf); X if (buf[len-1] == '\n') X buf[len-1] = '\0'; X if (basesize + len + 1 + sizeof(char *) >= XARGMAX) { X fprintf(stderr, "%s: filename too long: ", progname); X fputs(buf, stdout); X putchar('\n'); X } else { X if (size + len + 1 + sizeof(char *) >= XARGMAX) { X argptrs[nargs++] = NULL; X thisstat = runone(cmd, argptrs); X if (thisstat > maxstat) X maxstat = thisstat; X argfree = argbase; X nargs = base; X size = basesize; X } X (void) strcpy(argfree, buf); X argptrs[nargs++] = argfree; X argfree += len + 1; X size += len + 1 + sizeof(char *); X } X } X if (nargs > base) { /* If there are any loose ends... */ X argptrs[nargs++] = NULL; X thisstat = runone(cmd, argptrs); X if (thisstat > maxstat) X maxstat = thisstat; X } X X exit(maxstat); X} X X/* X * runone - run the command X */ Xint /* status of command */ Xrunone(cmd, ptrs) Xchar *cmd; Xchar **ptrs; X{ X register int pid; X int status; X int stexit, stcause; X register int wpid; X X#ifdef DEBUG X fprintf(stderr, "run %s ... %s %s ...\n", cmd, ptrs[0], ptrs[1]); X#endif X while ((pid = fork()) < 0) X sleep(10); X if (pid == 0) { /* Daughter. */ X close(0); X if (open("/dev/null", 0) != 0) { X fprintf(stderr, "%s: can't open /dev/null\n", progname); X exit(2); X } X execvp(cmd, ptrs); X fprintf(stderr, "%s: can't find `%s'\n", progname, cmd); X exit(2); X } else { /* Parent. */ X do { X wpid = wait(&status); X } while (wpid >= 0 && wpid != pid); X stexit = (status>>8)&0377; X stcause = status&0377; X if (stcause != 0 || stexit > OKSTAT) { X fprintf(stderr, "%s: `%s' failed\n", progname, cmd); X exit(2); X } X return(stexit); X } X /* NOTREACHED */ X} END_OF_FILE if test 3713 -ne `wc -c <'expire/xargs.c'`; then echo shar: \"'expire/xargs.c'\" unpacked with wrong size! fi # end of 'expire/xargs.c' fi if test -f 'libcnews/path.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'libcnews/path.c'\" else echo shar: Extracting \"'libcnews/path.c'\" \(3615 characters\) sed "s/^X//" >'libcnews/path.c' <<'END_OF_FILE' X/* X * news path names (and umask) X */ X X#include X#include X#include "news.h" X#include "newspaths.h" X X#ifndef NULL X#define NULL 0 X#endif X X#ifndef NEWSCTL X#define NEWSCTL "/usr/lib/news" X#endif X#ifndef NEWSARTS X#define NEWSARTS "/usr/spool/news" X#endif X#ifndef NEWSBIN X#define NEWSBIN "/usr/lib/newsbin" X#endif X#ifndef NEWSUMASK X#define NEWSUMASK 002 X#endif X Xstatic char *pwd = NULL; /* Current directory, NULL means unknown. */ Xstatic int dirsset = NO; /* Have the following been set? */ Xstatic char *arts; Xstatic char *bin; Xstatic char *ctl; X#define DIRS() if (!dirsset) setdirs() Xvoid setdirs(); X Xextern char *strcpy(); Xextern char *strcat(); Xextern char *getenv(); X Xextern void unprivileged(); /* user-supplied privilege dropper */ X X/* X - spoolfile - historical synonym for artfile X */ Xchar * Xspoolfile(base) Xchar *base; X{ X static char wholefile[MAXFILE]; X X DIRS(); X X if (base == NULL) { /* he just wants the directory */ X (void) strcpy(wholefile, arts); X return wholefile; X } X X if (pwd != NULL && STREQ(pwd, arts)) X (void) strcpy(wholefile, ""); X else { X (void) strcpy(wholefile, arts); X (void) strcat(wholefile, SFNDELIM); X } X (void) strcat(wholefile, base); X X return wholefile; X} X X/* X - artfile - best pathname for a file in NEWSARTS X */ Xchar * Xartfile(base) Xchar *base; X{ X return spoolfile(base); X} X X/* X - fullartfile - full pathname for a file in NEWSARTS X */ Xchar * Xfullartfile(base) Xchar *base; X{ X register char *p; X register char *pwdsave; X X pwdsave = pwd; X pwd = NULL; /* fool spoolfile() into giving full path */ X p = spoolfile(base); X pwd = pwdsave; X return p; X} X X/* X - fullspoolfile - historical synonym for fullartfile X */ Xchar * Xfullspoolfile(base) Xchar *base; X{ X return fullartfile(base); X} X X/* X - libfile - historical synonym for ctlfile X */ Xchar * Xlibfile(base) Xchar *base; X{ X static char wholefile[MAXFILE]; X X DIRS(); X X (void) strcpy(wholefile, ctl); X if (base != NULL) { X (void) strcat(wholefile, SFNDELIM); X (void) strcat(wholefile, base); X } X return wholefile; X} X X/* X - ctlfile - full pathname for a file in NEWSCTL X */ Xchar * Xctlfile(base) Xchar *base; X{ X return libfile(base); X} X X/* X - binfile - full pathname for a file in NEWSBIN X */ Xchar * Xbinfile(base) Xchar *base; X{ X static char wholefile[MAXFILE]; X X DIRS(); X X (void) strcpy(wholefile, bin); X if (base != NULL) { X (void) strcat(wholefile, SFNDELIM); X (void) strcat(wholefile, base); X } X return wholefile; X} X X/* X - cd - change to a directory, with checking X */ Xvoid Xcd(dir) Xchar *dir; X{ X if (chdir(dir) < 0) X errunlock("cannot chdir(%s)", dir); X pwd = dir; X} X X/* X - setdirs - set up directories from environment, for use by other functions X * X * Invokes user-supplied function unprivileged() if non-standard values used. X */ Xstatic void Xsetdirs() X{ X register char *p; X register int nonstd = NO; X X if (dirsset) X return; X X p = getenv("NEWSARTS"); X if (p == NULL) X arts = NEWSARTS; X else { X arts = p; X nonstd = YES; X } X X p = getenv("NEWSCTL"); X if (p == NULL) X ctl = NEWSCTL; X else { X ctl = p; X nonstd = YES; X } X X p = getenv("NEWSBIN"); X if (p == NULL) X bin = NEWSBIN; X else { X bin = p; X nonstd = YES; X } X X dirsset = YES; X if (nonstd) X unprivileged(); X} X X/* X - newsumask - return suitable value of umask for news stuff X */ Xint Xnewsumask() X{ X register char *p; X register char *scan; X register int mask; X X p = getenv("NEWSUMASK"); X if (p == NULL) X return(NEWSUMASK); X else { X mask = 0; X for (scan = p; *scan != '\0'; scan++) X if ('0' <= *scan && *scan <= '7' && mask <= 077) X mask = (mask << 3) | (*scan - '0'); X else /* Garbage, ignore it. */ X return(NEWSUMASK); X return(mask); X } X} END_OF_FILE if test 3615 -ne `wc -c <'libcnews/path.c'`; then echo shar: \"'libcnews/path.c'\" unpacked with wrong size! fi # end of 'libcnews/path.c' fi if test -f 'mail/coder/uudecode.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'mail/coder/uudecode.c'\" else echo shar: Extracting \"'mail/coder/uudecode.c'\" \(3280 characters\) sed "s/^X//" >'mail/coder/uudecode.c' <<'END_OF_FILE' X X/* based on 5.1 (Berkeley) 7/2/83 */ X X/* X * uudecode [input] X * X * create the specified file, decoding as you go. X * used with uuencode. X */ X#include X#include X#include X#include X Xmain(argc, argv) Xchar **argv; X{ X FILE *in, *out; X int mode = 0777; X char dest[128]; X char buf[80]; X char *strcpy(), *strcat(); X X /* optional input arg */ X if (argc > 1) { X if ((in = fopen(argv[1], "r")) == NULL) { X perror(argv[1]); X exit(1); X } X argv++; argc--; X } else X in = stdin; X X if (argc != 1) { X (void) fprintf(stderr, "Usage: uudecode [infile]\n"); X exit(2); X } X X /* search for header line */ X for (;;) { X if (fgets(buf, sizeof buf, in) == NULL) { X (void) fprintf(stderr, "No begin line\n"); X exit(3); X } X if (strncmp(buf, "begin ", 6) == 0) X break; X } X dest[0] = '\0'; X (void) sscanf(buf, "begin %o %s", &mode, dest); X X /* handle ~user/file format */ X if (dest[0] == '~') { X char *sl; X struct passwd *getpwnam(); X char *index(); X struct passwd *user; X char dnbuf[100]; X X sl = index(dest, '/'); X if (sl == NULL) { X (void) fprintf(stderr, "Illegal ~user\n"); X exit(3); X } X *sl++ = 0; X user = getpwnam(dest+1); X if (user == NULL) { X (void) fprintf(stderr, "No such user as %s\n", dest); X exit(4); X } X (void) strcpy(dnbuf, user->pw_dir); X (void) strcat(dnbuf, "/"); X (void) strcat(dnbuf, sl); X (void) strcpy(dest, dnbuf); X } X X /* create output file */ X out = fopen(dest, "w"); X if (out == NULL) { X perror(dest); X exit(4); X } X (void) chmod(dest, mode); X X decode(in, out); X X if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) { X (void) fprintf(stderr, "No end line\n"); X exit(5); X } X exit(0); X} X X/* X * copy from in to out, decoding as you go along. X */ Xdecode(in, out) XFILE *in; XFILE *out; X{ X register char *ibp, *obp; X register int inbyte, outbyte; X register int loops, incount; X char inbuf[120]; /* allow for uuencode to grow lines */ X char outbuf[120]; X X/* single character decode */ X#define DEC(c) (((c) - ' ') & 077) /* N.B.: c is evaluated exactly once */ X X for (; ; ) { X if (fgets(inbuf, sizeof inbuf, in) == NULL) { X (void) printf("Short file\n"); X exit(10); /* premature EOF */ X } X incount = DEC(inbuf[0]); X if (incount <= 0) X break; /* EOF */ X X ibp = &inbuf[1]; /* skip line length */ X obp = outbuf; X for (loops = incount / 3; --loops >= 0; ) { /* inner loop */ X /* X * output a group of 3 bytes (4 input characters). X * the input chars are pointed to by ibp, they are to X * be output via obp. incount is used to tell us X * not to output all of them at the end of the line. X */ X outbyte = DEC(*ibp++) << 2; X *obp++ = outbyte | ((inbyte = DEC(*ibp++)) >> 4); X outbyte = inbyte << 4; X *obp++ = outbyte | ((inbyte = DEC(*ibp++)) >> 2); X *obp++ = (inbyte << 6) | DEC(*ibp++); X } X loops = incount % 3; X if (loops > 0) { X /* X * finish off the remaining bytes (loops < 3). X */ X if (--loops >= 0) { X outbyte = DEC(*ibp++) << 2; X *obp++ = outbyte | ((inbyte = DEC(*ibp++)) >> 4); X } X if (--loops >= 0) { X outbyte = inbyte << 4; X *obp++ = outbyte | ((inbyte = DEC(*ibp++)) >> 2); X } X if (--loops >= 0) X *obp++ = (inbyte << 6) | DEC(*ibp++); X } X *obp = '\0'; X (void) fwrite(outbuf, 1, obp - outbuf, out); X } X} END_OF_FILE if test 3280 -ne `wc -c <'mail/coder/uudecode.c'`; then echo shar: \"'mail/coder/uudecode.c'\" unpacked with wrong size! fi # end of 'mail/coder/uudecode.c' fi if test -f 'rna/active.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'rna/active.c'\" else echo shar: Extracting \"'rna/active.c'\" \(3032 characters\) sed "s/^X//" >'rna/active.c' <<'END_OF_FILE' X/* X * active file handling routines X * X * format of file: X * ' ' <5 digit #> ' ' <5 digit #> ' ' flag '\n' X * (seq) (low) X */ X X#include "defs.h" X Xstatic char actname[] = ACTIVE; Xstatic int lineno; Xstatic active *alist; X X/* X * getseq - Get next sequence number for this group X * and update active file. X * If group missing append to file. X */ Xchar * Xgetseq(group) Xchar *group; X{ X register FILE *f; X register int i; X char gbuf[BUFSIZ / 2], dbuf[BUFSIZ / 4], dbuf2[BUFSIZ / 4]; X extern char *itoa(); X X f = fopenl(actname); X lineno = 0; X while (getline(f, gbuf, dbuf, dbuf2)) X if (CMP(gbuf, group) == 0) { X i = atoi(dbuf); X i++; X fseek(f, -12L, 1); X (void) fprintf(f, "%05d", i); X fclose(f); X#if !AUSAM X unlock(actname); X#endif X return itoa(i); X } X (void) fprintf(f, "%s 00001 00001 y\n", group); X fclose(f); X#if !AUSAM X unlock(actname); X#endif X return itoa(1); X} X X Xstatic Xgetline(f, g, d, d2) Xregister FILE *f; Xchar *g, *d, *d2; X{ X register int c; X register char *s; X X lineno++; X s = g; X while ((c = getc(f)) != ' ' && c != EOF) X *s++ = c; X *s = '\0'; X X if (c != EOF) { X s = d; X while ((c = getc(f)) != EOF && isdigit(c)) X *s++ = c; X *s = '\0'; X X s = d2; X if (c == ' ') X while ((c = getc(f)) != EOF && isdigit(c)) X *s++ = c; X *s = '\0'; X X if (c == ' ') X while ((c = getc(f)) != EOF && c != '\n') X ; /* eat flag */ X } X X if (c != EOF && (c != '\n' || !*d || !*d2)) X error("%s: bad format: line %d", actname, lineno); X return c != EOF; X} X X X/* X * build internal active file structure X */ Xactive * Xreadactive() X{ X register FILE *f; X register active *ap, *last; X char gbuf[BUFSIZ / 2], dbuf[BUFSIZ / 4], dbuf2[BUFSIZ / 4]; X X alist = last = NIL(active); X f = fopenf(actname, "r"); X lineno = 0; X while (getline(f, gbuf, dbuf, dbuf2)) { X ap = NEW(active); X ap->a_name = newstr(gbuf); X ap->a_seq = atoi(dbuf); X ap->a_low = atoi(dbuf2); X ap->a_next = NIL(active); X if (!alist) X alist = ap; X else X last->a_next = ap; X last = ap; X } X fclose(f); X return alist; X} X X X/* X * return pointer to named group X */ Xactive * Xactivep(grp) Xregister char *grp; X{ X register active *ap; X X for (ap = alist; ap; ap = ap->a_next) X if (CMP(grp, ap->a_name) == 0) X break; X return ap; X} X X X/* X * setlow - set the low number for this group X */ Xsetlow(group, low) Xchar *group; Xint low; X{ X register FILE *f; X char gbuf[BUFSIZ / 2], dbuf[BUFSIZ / 4], dbuf2[BUFSIZ / 4]; X extern char *itoa(); X X f = fopenl(actname); X lineno = 0; X while (getline(f, gbuf, dbuf, dbuf2)) X if (CMP(gbuf, group) == 0) { X fseek(f, -6L, 1); X (void) fprintf(f, "%05d", low); X break; X } X fclose(f); X#if !AUSAM X unlock(actname); X#endif X} X X X X/* X * initgrp - initialise an entry for this group X */ Xinitgrp(group) Xchar *group; X{ X register FILE *f; X char gbuf[BUFSIZ / 2], dbuf[BUFSIZ / 4], dbuf2[BUFSIZ / 4]; X X f = fopenl(actname); X lineno = 0; X while (getline(f, gbuf, dbuf, dbuf2)) X if (CMP(gbuf, group) == 0) { X#if !AUSAM X unlock(actname); X#endif X return; X } X (void) fprintf(f, "%s 00000 00001\n", group); X X} END_OF_FILE if test 3032 -ne `wc -c <'rna/active.c'`; then echo shar: \"'rna/active.c'\" unpacked with wrong size! fi # end of 'rna/active.c' fi if test -f 'rna/history.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'rna/history.c'\" else echo shar: Extracting \"'rna/history.c'\" \(3647 characters\) sed "s/^X//" >'rna/history.c' <<'END_OF_FILE' X/* X * History file X * each line contains a message-id, install or expire time X * names of linked files X */ X X#include "defs.h" X Xstatic char histname[] = HISTORY; Xstatic char *histid; /* messageid to save */ Xstatic char *histline; /* list of linked files */ Xstatic long etime; /* expire time */ X Xtypedef enum stypes { X chk, delete } stype; X X/* X * do things with history file X * chk - see if id present X * delete - delete article with id X */ Xstatic bool Xsearchhist(id, type) Xchar *id; Xstype type; X{ X register FILE *f; X register char *s, *name; X register bool found; X char buf[BUFSIZ * 2]; X X extern char *newsdir; X X f = fopenl(histname); X X found = false; X while (fgets(buf, sizeof(buf), f)) { X if (s = strchr(buf, ' ')) X *s = '\0'; X else X error("Bad format: %s", histname); X if (CMP(buf, id) == 0) { X found = true; X break; X } X } X if (found && type == delete) { X if ((name = strchr(s + 1, ' ')) == NIL(char)) X error("Bad format: %s", histname); X name++; X while (name && (s = strpbrk(name, " \n"))) { X *s = '\0'; X name = newstr3(newsdir, "/", name); X remove(name); X free(name); X name = s + 1; X } X } X fclose(f); X#if !AUSAM X unlock(histname); X#endif X return found; X} X X X/* X * delete files given id X */ Xbool Xcancel(id) Xchar *id; X{ X bool searchhist(); X X return searchhist(id, delete); X} X X X/* X * check if article has been recieved X */ Xbool Xchkhist(id) Xchar *id; X{ X bool searchhist(); X X return searchhist(id, chk); X} X X X/* X * scan history, clearing uflag list entry if id not seen X */ Xscanhist(ulist, usize) Xchar **ulist; Xint usize; X{ X register FILE *f; X register char *s, **found; X register int i; X char *key[1]; X char buf[BUFSIZ * 2]; X bool * seen; X X extern char *newsdir; X X seen = (bool * ) myalloc((int) sizeof(bool) * usize); X memset((char *)seen, 0, (int) sizeof(bool) * usize); X X f = fopenf(histname, "r"); X while (fgets(buf, sizeof(buf), f)) { X if (s = strchr(buf, ' ')) X *s = '\0'; X else X error("Bad format: %s", histname); X key[0] = buf; X found = (char **) bsearch((char *) key, (char *) ulist, (unsigned) usize, X sizeof(char *), strpcmp); X if (found) X seen[found - ulist] = true; X } X fclose(f); X X for (i = 0; i < usize; i++) X if (!seen[i]) { X free(ulist[i]); X ulist[i] = NIL(char); X } X free((char *)seen); X} X X X/* X * open hist file, write id and time X */ Xopenhist(hp) Xheader *hp; X{ X X histid = newstr(hp->h_messageid); X if (hp->h_expires) X etime = atot(hp->h_expires); X else X etime = 0L; X histline = NIL(char); X} X X X/* X * write name of file article resides into history file X */ Xwritehist(fname) Xchar *fname; X{ X histline = (histline ? catstr2(histline, " ", fname) : newstr(fname)); X} X X X/* X * close history file X */ Xclosehist() X{ X register FILE *f; X extern long now; X X f = fopenl(histname); X fseek(f, 0L, 2); X (void) fprintf(f, "%s %s%ld %s\n", histid, etime ? "E" : "", etime ? etime : X now, histline); X fclose(f); X#if !AUSAM X unlock(histname); X#endif X free(histid); X free(histline); X} X X X/* X * remove a news item X * check owner first X */ Xstatic Xremove(fname) Xchar *fname; X{ X header h; X FILE * f; X register char *s, *mname; X X#if AUSAM X extern struct pwent pe; X#else X extern struct passwd *pp; X#endif X extern char systemid[]; X extern bool su; X extern bool pflag; X X if (!su && !pflag) { X f = fopenf(fname, "r"); X gethead(f, &h); X fclose(f); X if (s = strchr(h.h_from, ' ')) X *s = '\0'; X mname = newstr5( X#if AUSAM X pe.pw_strings[LNAME], X#else X pp->pw_name, X#endif X "@", systemid, ".", MYDOMAIN); X if (CMP(mname, h.h_from) != 0) X error("Can't cancel articles you didn't write."); X free(mname); X } X if (unlink(fname) != 0) X error("Couldn't unlink %s", fname); X X} END_OF_FILE if test 3647 -ne `wc -c <'rna/history.c'`; then echo shar: \"'rna/history.c'\" unpacked with wrong size! fi # end of 'rna/history.c' fi if test -f 'rnews/README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'rnews/README'\" else echo shar: Extracting \"'rnews/README'\" \(3793 characters\) sed "s/^X//" >'rnews/README' <<'END_OF_FILE' XThis is an alpha test release. Do not distribute modified copies of it; Xsee the COPYRIGHT file for details. X XSend bug reports to utzoo!cnews-alpha. This software is believed to Xwork, though it could doubtless stand some improvement. The code is Xgoing to be cleaned up and possibly sped up before general release. X X X``yer about to be boarded, ye scurvy network news dogs! har har ...'' X -- Oliver Wendell Jones, Bloom County Hacker & Cracker X X``No news is good news.'' X``When bigger machines are built, netnews will saturate them.'' X``USENET -- All the news that's fit to `N'.'' X -- /usr/games/fortune X X``B news is Bad news.'' X``Net news is the television of computing.'' X -- Geoff Collyer X XDoes your inews wallow in the mud like a pregnant sow? Does your expire Xflop on its back, wiggle its feet and gurgle pathetically? Then you Xneed new, improved *C news*, the sentient being's news system: no more Xodious Relay-Version headers, no more sluggish machines caused by Xoverfed news software. Real locking. No line-eater bugs. X XAvailable from fine news administrators everywhere. C news. X___ X XAssumptions: X you already have B news and possibly rn running X you personally installed B news X you are now upgrading to C news X XBefore using make for anything else, you must X X make variant X Xwhere variant is your UNIX variant: v7, v8, v9, bsd42 or usg. XIt will tell you to edit the makefile DEPSRC and DEPOBJ definitions to match. X XIf you need a roadmap, see ../usr.lib/README. X X../expire and ../time require that /usr/include/time.h exists. XIf it doesn't exist on your (4.2BSD) system, thanks to gratuitous Xtinkering (at UCB), execute X X cd /usr/include; ln -s sys/time.h X XThis may require super-user privileges, which should be easy to obtain Xon 4.2. X XAfter compiling inews, install it as /usr/lib/news/realinews, Xsetuid-news. On older systems, you will to also install a small Xprogram, setnewids, setuid-root. If this worries you, read Xsetnewsids.c; all it does is execute setgid(), setuid() to the "news" Xgroup and user if they exist, otherwise realinews's real ids. Install Xsh/inews as /usr/bin/inews, rnews.sh as /usr/bin/rnews and X/usr/bin/cunbatch. You can test realinews by giving NEWSCTL, NEWSBIN Xor NEWSARTS environment variables to change the library, binary or Xspool directories and I encourage this. X XIf you plan to run rn, you'll need the latest rn patches to allow Xref: Xto work without Relay-Version:. X XYou can get postnews from B news & Pnews from rn. X XYour sys file should not refer to a given batch file (with the F or f Xflags) more than once, or the batch file will be scrambled; this will be Xfixed and isn't a disaster as the C batcher is quite flexible and can Xcompensate. The Ln flag isn't yet fully implemented. X XIf your `domain' isn't "uucp", you will need to put your domain name in X/usr/lib/news/domain. No upper case letters in your new domain please, Xthere is no call for it and it just looks ugly. X XYou must remove /usr/lib/news/LOCK* and /usr/lib/news/lock.* somewhere Xin /etc/rc*. Thus you must only permit rnews to run on file servers. X XYou'll need compress for compressing or uncompressing batches of news. XSee the contact person of your news feed or the moderator of the Xnewsgroup comp.sources.unix. X XSee the anews directory for conversion filters from A to B and back. X XYou'll need to install /usr/lib/news/gngp (see ../gngp) before inews Xwill work. X XB-2.11-isms: your /usr/lib/news/mailpaths file must be updated to point Xat your nearest backbone site. A 5th sys file field for Distribution: Xpatterns is here (add them in sys after the subscription list, separated Xby "/"), and a 6th field for excluded hosts is half-here, separated by X"/" from the system name. Active file support for 4 fields and the m Xflag are here. X XGood Luck. X X Geoff Collyer END_OF_FILE if test 3793 -ne `wc -c <'rnews/README'`; then echo shar: \"'rnews/README'\" unpacked with wrong size! fi # end of 'rnews/README' fi if test -f 'rnews/active.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'rnews/active.c'\" else echo shar: Extracting \"'rnews/active.c'\" \(3462 characters\) sed "s/^X//" >'rnews/active.c' <<'END_OF_FILE' X/* X * active file access functions (in-memory version) X */ X X#include X#include X#include X#include "active.h" X#include "news.h" X#include "newspaths.h" X X#define MAXNGS 2000 X Xstatic FILE *fp = NULL; Xstatic char filerelname[] = "active"; Xstatic char *active = NULL; /* points at entire active file */ Xstatic int actsize; /* bytes in active: type int determined by fread */ Xstatic unsigned artlines; /* lines in artlnps actually used */ X/* TODO: make this a linked list or realloc to avoid the MAXNGS limit */ Xstatic char *artlnps[MAXNGS]; /* point at lines in active file */ X Xlong Xincartnum(ng, inc) Xchar *ng; Xint inc; X{ X register int nglen = strlen(ng); X register char *pos; X register unsigned line = 0; X register long nextart = -1; X char artnumstr[ARTNUMWIDTH + 1]; X extern char ldzeropad[]; X X if (artload() != ST_OKAY) X return nextart; X while (pos = artlnps[line], line++ < artlines && pos[0] != '\0') X if (STREQN(pos, ng, nglen) && pos[nglen] == ' ') { X nextart = atol(&pos[nglen + 1]) + inc; X (void) sprintf(artnumstr, ldzeropad, X ARTNUMWIDTH, ARTNUMWIDTH, nextart); X (void) strncpy(&pos[nglen + 1], artnumstr, ARTNUMWIDTH); X break; X } X return nextart; X} X Xint Xartload() /* reload any cached data */ X{ X int status = 0; X X if (fp == NULL) X if ((fp = fopenwclex(libfile(filerelname), "r+")) == NULL) X status |= ST_DROPPED; X if (fp != NULL && active == NULL) { /* file open, no cache */ X struct stat sb; X X if (fstat(fileno(fp), &sb) < 0) X warning("can't fstat %s", libfile(filerelname)); X else if (actsize = sb.st_size, /* squeeze into an int */ X (unsigned)actsize != sb.st_size) X warning("%s won't fit into memory", libfile(filerelname)); X else if ((active = malloc((unsigned)actsize+1)) == NULL) X warning("can't allocate memory for %s", libfile(filerelname)); X else { X rewind(fp); X /* TODO: read with fgets to avoid linescan() */ X if (fread(active, 1, actsize, fp) != actsize) { X warning("error reading %s", libfile(filerelname)); X free(active); X active = NULL; X } else { X active[actsize] = '\0'; /* make a proper string */ X if ((artlines = linescan(active, artlnps, X MAXNGS)) >= MAXNGS) { X extern char *progname; X X (void) fprintf(stderr, X "%s: too many newsgroups in %s\n", X progname, libfile(filerelname)); X free(active); X active = NULL; X } X } X } X if (active == NULL) X status |= ST_DROPPED; /* give up! */ X } X return status; X} X Xint Xartsync() /* sync to disk any cached data */ X{ X int status = 0; X X if (fp != NULL) { X rewind(fp); X if (active != NULL && fwrite(active, actsize, 1, fp) != 1 || X fclose(fp) == EOF) { X warning("error writing %s", libfile(filerelname)); X status |= ST_DROPPED; X } X } X fp = NULL; X if (active != NULL) X free(active); /* give back memory active used */ X active = NULL; X return status; X} X X/* X * Store in lnarray the addresses of the starts of lines in s. X * Return the number of lines found; if greater than nent, X * store only nent and return nent. X */ Xint Xlinescan(s, lnarray, nent) Xregister char *s; Xregister char **lnarray; Xregister int nent; X{ X register int i = 0; X register char *nlp = s; X X if (i < nent) X lnarray[i++] = s; X while (i < nent && (nlp = index(nlp, '\n')) != NULL) X lnarray[i++] = ++nlp; X return i; X} X X/* ARGSUSED hdrs */ Xmoderated(hdrs) Xstruct headers *hdrs; X{ X /* TODO: look at 4th field of active file; needs new active.c hook */ X return NO; /* stub */ X} END_OF_FILE if test 3462 -ne `wc -c <'rnews/active.c'`; then echo shar: \"'rnews/active.c'\" unpacked with wrong size! fi # end of 'rnews/active.c' fi if test -f 'rnews/makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'rnews/makefile'\" else echo shar: Extracting \"'rnews/makefile'\" \(3080 characters\) sed "s/^X//" >'rnews/makefile' <<'END_OF_FILE' X# makefile for C news relaynews X X# define NOSTOREVAL if your dbm store() returns no value (as in orig. v7) X# -I. for fcntl.h if present XDEFINES= -I../include -I. -DSTATIC= X# -Dvoid=int # if your compiler doesn't understand void's X# -DMAXLONG=017777777777L # if your compiler lacks "unsigned long" type X# -Dindex=strchr -Drindex=strrchr # if not on (System III or V or PWB) X XCFLAGS=-O -f68881 $(DEFINES) # -pg # -Z: John Bruner's Z0MAGIC (unmapped first page) XLIBS= -ldbm # -lstdio XLLIBS=-llocal XPROPTS=-l132 XP=impr -p X XPOSSDEPFILES=fcntl.h gethostname.c getwd.c dbm.c mkdir.c ftime.c clsexec.c memcpy.c X# adjust next three lines for your OS; sources are links to vers/*/*.c XDEPHDR= XDEPSRC= clsexec.c memcpy.c zeropad.c XDEPOBJ= clsexec.o memcpy.o zeropad.o X XLIBSRCS= ../libcnews/*.c XLIBOBJS= ../libcnews/libcnews.a ../libc/libc.a XSRC=relaynews.c active.c caches.c checkdir.c control.c fileart.c \ X headers.c history.c hostname.c io.c msgs.c procart.c \ X string.c sys.c transmit.c $(DEPSRC) $(LIBSRCS) XOBJ=relaynews.o active.o caches.o checkdir.o control.o fileart.o \ X headers.o history.o hostname.o io.o msgs.o procart.o \ X string.o sys.o transmit.o $(DEPOBJ) $(LIBOBJS) XFILES=$(NONCFILES) $(CFILES) XNONCFILES= TODO* COPYRIGHT README ads/README ads/[0-9]* \ X inews anne.jones tear rnews makefile XCFILES= ../include/*.h cpu.h headers.h system.h $(DEPHDR) $(SRC) XLINT=lint XLINTFLAGS=-haz $(DEFINES) X Xrelaynews: $(OBJ) ../libcnews/*.c X (cd ../libcnews; make) X $(CC) $(CFLAGS) $(OBJ) $(LIBS) -o $@ Xlint: $(SRC) X $(LINT) $(LINTFLAGS) $(SRC) $(LIBS) $(LLIBS) | egrep -v ':$$' Xlintport: $(SRC) X $(LINT) $(LINTFLAGS) -p $(SRC) $(LIBS) $(LLIBS) X XTODO.grep: TODO X -egrep TODO TODO ../include/*.h *.h *.c sh/* >$@ X -egrep TODO ../libc/memcpy.fast/src/*.c ../libcnews/*.c >>$@ X Xv7 v8 v9 usg bsd42: clean X for file in vers/$@/*.c; do ln $$file; done X @echo 'Now edit makefile DEPSRC and DEPOBJ definitions to match:' X @echo vers/$@/*.c | sed 's;vers/$@/;;g' X Xprint: printc printnonc X touch $@ Xprintc: $(CFILES) X /usr/bin/pp -T300 -fR $? | dimp -t | impr X touch $@ Xprintnonc: $(NONCFILES) X pr $(PROPTS) $? | $P X touch $@ Xdistr: $(FILES) X (echo relaynews update of `date`; echo ""; bundle $?) | /bin/mail cnews-updates X touch $@ Xclean: X rm -f core a.out relaynews *.o $(POSSDEPFILES) X X# header dependencies follow Xactive.o: active.h ../include/news.h ../include/newspaths.h Xcaches.o: ../include/news.h Xcheckdir.o: ../include/news.h Xcontrol.o: ../include/news.h ../include/newspaths.h headers.h history.h Xfileart.o: ../include/news.h ../include/newspaths.h active.h headers.h system.h Xheaders.o: ../include/news.h headers.h Xhistory.o: ../include/news.h ../include/newspaths.h headers.h Xhostname.o: ../include/news.h ../include/newspaths.h Xio.o: ../include/news.h Xmsgs.o: ../include/news.h Xprocart.o: ../include/news.h active.h headers.h system.h Xrelaynews.o: ../include/news.h ../include/newspaths.h active.h cpu.h headers.h system.h Xstring.o: ../include/news.h Xsys.o: ../include/news.h ../include/newspaths.h system.h Xtransmit.o: ../include/news.h ../include/newspaths.h headers.h system.h END_OF_FILE if test 3080 -ne `wc -c <'rnews/makefile'`; then echo shar: \"'rnews/makefile'\" unpacked with wrong size! fi # end of 'rnews/makefile' fi if test -f 'rnews/speed/mem/active.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'rnews/speed/mem/active.c'\" else echo shar: Extracting \"'rnews/speed/mem/active.c'\" \(3682 characters\) sed "s/^X//" >'rnews/speed/mem/active.c' <<'END_OF_FILE' X/* X * active file access functions (in-memory version) X * TODO: use hashing for speed & to eliminate MAXNGS X */ X X#include X#include X#include X#include "news.h" X X#define MAXNGS 2000 X Xstatic FILE *fp = NULL; Xstatic char filerelname[] = "active"; Xstatic char *active = NULL; /* points at entire active file */ Xstatic int actsize; /* bytes in active: type int determined by fread */ Xstatic unsigned artlines; /* lines in artlnps actually used */ X/* TODO: make this a linked list to avoid the MAXNGS limit? */ Xstatic char *artlnps[MAXNGS]; /* point at lines in active file */ X X/* TODO: make these two macros in a header file? */ Xlong Xnxtartnum(ng) Xchar *ng; X{ X long incartnum(); X X return incartnum(ng, 1); X} X Xlong Xprevartnum(ng) Xchar *ng; X{ X long incartnum(); X X return incartnum(ng, -1); X} X Xstatic long Xincartnum(ng, inc) Xchar *ng; Xint inc; X{ X register int nglen = strlen(ng); X register char *pos; X register unsigned line = 0; X register long nextart = -1; X char artnumstr[ARTNUMWIDTH + 1]; X extern char ldzeropad[]; X char *sprintf(), *strncpy(); X long atol(); X X if (artload() != ST_OKAY) X return nextart; X while (pos = artlnps[line], line++ < artlines && pos[0] != '\0') X if (STREQN(pos, ng, nglen) && pos[nglen] == ' ') { X nextart = atol(&pos[nglen + 1]) + inc; X (void) sprintf(artnumstr, ldzeropad, X ARTNUMWIDTH, ARTNUMWIDTH, nextart); X (void) strncpy(&pos[nglen + 1], artnumstr, ARTNUMWIDTH); X break; X } X return nextart; X} X Xint Xartload() /* reload any cached data */ X{ X int status = 0; X char *libfile(); X FILE *fopenwclex(); X X if (fp == NULL) X if ((fp = fopenwclex(libfile(filerelname), "r+")) == NULL) X status |= ST_DROPPED; X if (fp != NULL && active == NULL) { /* file open, no cache */ X struct stat sb; X char *malloc(); X X if (fstat(fileno(fp), &sb) < 0) X warning("can't fstat %s", libfile(filerelname)); X else if (actsize = sb.st_size, /* squeeze into an int */ X (unsigned)actsize != sb.st_size) X warning("%s won't fit into memory", libfile(filerelname)); X else if ((active = malloc((unsigned)actsize+1)) == NULL) X warning("can't allocate memory for %s", libfile(filerelname)); X else { X rewind(fp); X /* TODO: read with fgets to avoid linescan() */ X if (fread(active, 1, actsize, fp) != actsize) { X warning("error reading %s", libfile(filerelname)); X free(active); X active = NULL; X } else { X active[actsize] = '\0'; /* make a proper string */ X if ((artlines = linescan(active, artlnps, X MAXNGS)) >= MAXNGS) { X extern char *progname; X X (void) fprintf(stderr, X "%s: too many newsgroups in %s\n", X progname, libfile(filerelname)); X free(active); X active = NULL; X } X } X } X if (active == NULL) X status |= ST_DROPPED; /* give up! */ X } X return status; X} X Xint Xartsync() /* sync to disk any cached data */ X{ X int status = 0; X char *libfile(); X X if (fp != NULL) { X rewind(fp); X if (active != NULL && fwrite(active, actsize, 1, fp) != 1) { X warning("error writing %s", libfile(filerelname)); X status |= ST_DROPPED; X } X if (fclose(fp) == EOF) X status |= ST_DROPPED; X } X fp = NULL; X if (active != NULL) X free(active); /* give back memory active used */ X active = NULL; X return status; X} X X/* X * Store in lnarray the addresses of the starts of lines in s. X * Return the number of lines found; if greater than nent, X * store only nent and return nent. X */ Xint Xlinescan(s, lnarray, nent) Xregister char *s; Xregister char **lnarray; Xregister int nent; X{ X register int i = 0; X register char *nlp = s; X char *index(); X X if (i < nent) X lnarray[i++] = s; X while (i < nent && (nlp = index(nlp, '\n')) != NULL) X lnarray[i++] = ++nlp; X return i; X} END_OF_FILE if test 3682 -ne `wc -c <'rnews/speed/mem/active.c'`; then echo shar: \"'rnews/speed/mem/active.c'\" unpacked with wrong size! fi # end of 'rnews/speed/mem/active.c' fi if test -f 'rnews/speed/mem/sys.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'rnews/speed/mem/sys.c'\" else echo shar: Extracting \"'rnews/speed/mem/sys.c'\" \(4014 characters\) sed "s/^X//" >'rnews/speed/mem/sys.c' <<'END_OF_FILE' X/* X * inews sys file reading functions (in-memory version) X */ X X#include X#include X#include X#include "news.h" X#include "system.h" X Xstatic FILE *fp = NULL; /* descriptor for libfile("sys") */ Xstatic char filerelname[] = "sys"; Xstatic char defaultcmd[] = "exit 1"; /* reminder to bozo admins */ Xstatic struct system *firstsys = NULL; /* cache */ Xstatic struct system *currsys = NULL; /* current system */ X Xstruct system * Xoursys() /* return our sys entry */ X{ X register struct system *sys; X static struct system fakesys; X char *hostname(); X struct system *nextsys(); X X rewsys(); X while ((sys = nextsys()) != NULL && !STREQ(sys->sy_name, hostname())) X ; X if (sys == NULL) { /* no entry; cook one up */ X fakesys.sy_name = hostname(); X fakesys.sy_ngs = "all"; X fakesys.sy_flags = 0; X fakesys.sy_lochops = 0; X fakesys.sy_cmd = defaultcmd; X fakesys.sy_next = NULL; X sys = &fakesys; X } X return sys; X} X X/* X * Returned pointer points at a static struct whose members X * point at static storage. X */ Xstruct system * Xnextsys() /* return next sys entry */ X{ X struct system *retsys; X char *libfile(); X FILE *fopenwclex(); X X if (firstsys == NULL && fp == NULL) X if ((fp = fopenwclex(libfile(filerelname), "r")) == NULL) X return NULL; X if (fp != NULL && firstsys == NULL) /* file open, no cache */ X readsys(); /* read & parse fp */ X retsys = currsys; /* save current ptr. */ X if (currsys != NULL) X currsys = currsys->sy_next; /* advance current ptr. */ X return retsys; X} X Xrewsys() X{ X currsys = firstsys; X} X Xstatic char *curr, *next; /* parsing state */ X Xstatic Xreadsys() X{ X char sysline[MAXLINE]; X X rewind(fp); X /* TODO: write & use cfgets to read continued lines (need bigger MAXLINE) */ X while (fgets(sysline, sizeof sysline, fp) != NULL) X if (sysline[0] != '#' && sysline[0] != '\n') { /* not a comment */ X register struct system *sysp; X char *flagstring; X char *malloc(); X X sysp = (struct system *)malloc(sizeof *sysp); X if (sysp == NULL) X errunlock("out of memory for system structs", ""); X X /* parse into sysp */ X trim(sysline); X next = sysline; X parse(&sysp->sy_name); X parse(&sysp->sy_ngs); X parse(&flagstring); X parse(&sysp->sy_cmd); X /* could check for extra fields here */ X sysp->sy_flags = flgtobits(flagstring); X sysp->sy_lochops = 0; /* Ln value someday */ X free(flagstring); /* malloced by parse */ X sysp->sy_next = NULL; X X /* fill in any defaults */ X if (sysp->sy_cmd[0] == '\0') { X free(sysp->sy_cmd); /* malloced by parse */ X sysp->sy_cmd = defaultcmd; /* NB not malloced */ X } X X /* stash *sysp away on the tail of the current list */ X if (firstsys == NULL) X firstsys = sysp; /* 1st system */ X else X currsys->sy_next = sysp; /* tack on tail */ X currsys = sysp; X } X (void) fclose(fp); /* file no longer needed */ X fp = NULL; /* mark file closed */ X rewsys(); X} X Xparse(into) Xregister char **into; X{ X char *strsave(), *parsecolon(); X X curr = next; X if (curr == NULL) X *into = strsave(""); X else { X next = parsecolon(curr); X *into = strsave(curr); X } X if (*into == NULL) X errunlock("out of memory for sys strings", ""); X} X Xchar * Xparsecolon(line) /* return NULL or ptr. to byte after colon */ Xchar *line; X{ X register char *colon; X X INDEX(line, ':', colon); X if (colon != NULL) X *colon++ = '\0'; /* turn colon into a NUL */ X return colon; X} X Xstatic int Xflgtobits(s) Xregister char *s; X{ X register int bits = 0; X X for (; *s != '\0'; s++) X switch (*s) { X case 'A': X errunlock("A news format not supported", ""); X /* NOTREACHED */ X case 'B': /* mostly harmless */ X break; X case 'F': X bits |= FLG_BATCH; X break; X case 'L': X bits |= FLG_LOCAL; X /* TODO: parse Ln, but maybe not here */ X break; X case 'N': X bits |= FLG_IHAVE; X errunlock("N flag given but I-have/send-me is not supported", ""); X /* NOTREACHED */ X case 'U': X bits |= FLG_PERM; X break; X default: X errunlock("unknown sys flag `%s' given", s); X /* NOTREACHED */ X } X return bits; X} END_OF_FILE if test 4014 -ne `wc -c <'rnews/speed/mem/sys.c'`; then echo shar: \"'rnews/speed/mem/sys.c'\" unpacked with wrong size! fi # end of 'rnews/speed/mem/sys.c' fi echo shar: End of archive 6 \(of 14\). ## End of shell archive. exit 0