henry@utzoo.uucp (Henry Spencer) (09/17/89)
(See accompanying article for explanation of correction.) Well, dbz is still "in the works" -- I've been busy -- but here's the latest batch of (mostly) small stuff. The big one here is that (with the exception of superkludge, whose days are numbered anyway), we now 100.000% comply with RFC822's rules about case-sensitivity in header keywords and message-IDs. (Note that B News is not RFC822-compliant on message-IDs, which are only *partly* [!] case-insensitive.) Unless you want duplicate checking to fail temporarily, you will need to rebuild your dbm/dbz indexes to the history file when installing this. (The history file itself is unchanged.) There are some #ifdefs in libcnews/case.c to give you B News behavior, if you really want it. Other changes: The usual minor cleanup and fixes for small annoyances. A new transmitter for the batcher, viarsh. Robustness fixes in history rebuilding. A warning message when configuration mismatches (or testing) cause programs to renounce setuid status. Robustness improvements in the fast-stdio stuff, which may let it run on more systems. Fix for a bug in change-moderation-status's newsgroup matching. Slightly less noise from checkgroups. Inews now passes formfeeds. Inews -p now works better. A new program, recovact, to help recover an active file after problems. And inews's rsh handling has been cleaned up and revised, which should cure assorted minor problems. start of patch 14-Sep-1989 (suggested archive name: `pch14Sep89.Z') this should be run with patch -p0 <thisfile The following is a complete list of patches to date. Prereq: 23-Jun-1989 Prereq: 7-Jul-1989 Prereq: 23-Jul-1989 Prereq: 22-Aug-1989 Prereq: 24-Aug-1989 *** tmp.dates.with.really.long.filename.for.patch Thu Sep 14 15:51:07 1989 --- PATCHDATES Thu Sep 14 15:51:07 1989 *************** *** 1,5 **** --- 1,6 ---- 23-Jun-1989 7-Jul-1989 23-Jul-1989 22-Aug-1989 24-Aug-1989 + 14-Sep-1989 Changed files, if any: *** cnpatch/tmp.file Thu Sep 14 15:51:12 1989 --- batch/Makefile Sat Aug 26 22:48:38 1989 *************** *** 17,24 **** PGMS=batcher batchih batchsm batchsplit comp compcun nocomp viainews viauux \ sendbatches compc7 c7encode viamail viapmail bencode compb viauuxz \ ! viaemail DTR=Makefile batcher.c batchih batchsplit c7encode.c comp compc7 compcun \ newsbatch.8 nocomp sendbatches viainews viauux viamail \ ! bencode.c coder.h crctab.c compb viapmail ALL = $(PGMS) batchparms --- 17,24 ---- PGMS=batcher batchih batchsm batchsplit comp compcun nocomp viainews viauux \ sendbatches compc7 c7encode viamail viapmail bencode compb viauuxz \ ! viaemail viarsh DTR=Makefile batcher.c batchih batchsplit c7encode.c comp compc7 compcun \ newsbatch.8 nocomp sendbatches viainews viauux viamail \ ! bencode.c coder.h crctab.c compb viapmail viarsh ALL = $(PGMS) batchparms *** cnpatch/tmp.file Thu Sep 14 15:51:22 1989 --- conf/build Tue Aug 29 16:43:42 1989 *************** *** 994,997 **** --- 994,999 ---- echo "echo 'general 0000000000 0000000001 y' >active" echo "echo 'news.announce.newusers 0000000000 0000000001 y' >>active" + echo "echo 'control 0000000000 0000000001 y' >>active" + echo "echo 'junk 0000000000 0000000001 y' >>active" echo ">errlog" echo ">history" *************** *** 1083,1086 **** --- 1085,1089 ---- echo " chmod +x $newsconfig" echo "fi" + echo "$newsbin/maint/adddirs" echo ": It is virtually certain that some of those control files" echo ": need modifying to suit your system. In particular, you" *** cnpatch/tmp.file Thu Sep 14 15:51:30 1989 --- conf/spacefor.proto Tue Aug 29 19:22:20 1989 *************** *** 22,26 **** if test " $server" != " $me" then ! exec rsh $server "PATH=$PATH `basename $0` $*" # does not return fi --- 22,26 ---- if test " $server" != " $me" then ! exec rsh $server /bin/sh -c "'PATH=$PATH `basename $0` $*'" # does not return fi *** cnpatch/tmp.file Thu Sep 14 15:51:32 1989 --- conf/subst.hs Wed Sep 13 16:50:55 1989 *************** *** 42,43 **** --- 42,45 ---- notebook/config batch/batchih + expire/recovact + misc/adddirs *** cnpatch/tmp.file Thu Sep 14 15:51:32 1989 --- conf/sys.proto Tue Aug 29 19:30:01 1989 *************** *** 20,24 **** # Send ihave telling louie what we have -- batcher turns the batch into a # giant control message and posts it to "to.louie". (#1) ! louie:rec.music.synth/all,!sendme,!ihave:I:louie.ihave/togo # Send sendme in response to ihave from louie -- again, turned by batcher # into giant control message posted to "to.louie". (#3) --- 20,24 ---- # Send ihave telling louie what we have -- batcher turns the batch into a # giant control message and posts it to "to.louie". (#1) ! louie:rec.music.synth,!to/all,!sendme,!ihave:I:louie.ihave/togo # Send sendme in response to ihave from louie -- again, turned by batcher # into giant control message posted to "to.louie". (#3) *** cnpatch/tmp.file Thu Sep 14 15:51:34 1989 --- contrib/dbz Thu Sep 14 15:36:16 1989 *************** *** 174,177 **** --- 174,179 ---- /* lcase(buffer, key.dsize); lcase is a B news botch */ + buffer[key.dsize] = '\0'; + (void) rfc822ize(buffer); if (buffer[key.dsize - 1] == '\t') { buffer[key.dsize - 1] = '\0'; *** cnpatch/tmp.file Thu Sep 14 15:51:48 1989 --- expire/Makefile Thu Sep 14 15:50:17 1989 *************** *** 7,14 **** LIBS= ../libcnews.a THEM = expire histdups histinfo histslash mkdbm mkhistory \ ! superkludge upact doexpire mkadir DTR = README Makefile dircheck doexpire expire.c histdups histinfo.c \ histslash.c mkdbm.c mkhistory pgood superkludge tgood upact \ ! mkadir updatemin.c UPACT=upact # =()<NEWSARTS = @<NEWSARTS>@>()= --- 7,14 ---- LIBS= ../libcnews.a THEM = expire histdups histinfo histslash mkdbm mkhistory \ ! superkludge upact doexpire mkadir recovact DTR = README Makefile dircheck doexpire expire.c histdups histinfo.c \ histslash.c mkdbm.c mkhistory pgood superkludge tgood upact \ ! mkadir updatemin.c recovact UPACT=upact # =()<NEWSARTS = @<NEWSARTS>@>()= *************** *** 212,219 **** test ! -f arts/urp/99 ; cmp history history.after ! : "that's it for expire, on to upact" $(D) ./$(UPACT) cmp active active.after $(D) ./$(UPACT) cmp active active.after : "and for upact, on to mkhistory" --- 212,224 ---- test ! -f arts/urp/99 ; cmp history history.after ! : "that's it for expire, on to upact and recovact" $(D) ./$(UPACT) cmp active active.after $(D) ./$(UPACT) + cmp active active.after + $(D) ./recovact + cmp active active.after + sed '/^foo /s/99/09/' active.after >active + $(D) ./recovact cmp active active.after : "and for upact, on to mkhistory" *** cnpatch/tmp.file Thu Sep 14 15:51:51 1989 --- expire/expire.c Wed Sep 13 21:02:42 1989 *************** *** 77,80 **** --- 77,81 ---- int verbose = 0; /* report statistics */ int rebuild = 1; /* rebuild history files */ + int violate = 0; /* non-rfc822 case-sensitive messageIDs */ long nkept = 0; /* count of articles not expired */ *************** *** 167,171 **** ftime(&ftnow); ! while ((c = getopt(argc, argv, "pa:sF:cn:tlvrd")) != EOF) switch (c) { case 'p': /* print info line for archived articles */ --- 168,172 ---- ftime(&ftnow); ! while ((c = getopt(argc, argv, "pa:sF:cn:tlvrVd")) != EOF) switch (c) { case 'p': /* print info line for archived articles */ *************** *** 199,202 **** --- 200,206 ---- rebuild = 0; break; + case 'V': /* non-rfc822 dualcase messageIDs */ + violate = 1; + break; case 'd': /* debug */ expdebug = 1; *************** *** 215,220 **** setbuf(stderr, (char *)NULL); - (void) cistrncmp("a", "a", 1); /* prime case.c */ - if (optind < argc) { cf = eufopen(argv[optind], "r"); --- 219,222 ---- *************** *** 433,436 **** --- 435,439 ---- datum rhs; register int ret; + register char *id; cd(ctlfile((char *)NULL)); *************** *** 464,469 **** /* make the DBM entry */ *nameend = '\0'; ! lhs.dptr = line; ! lhs.dsize = strlen(line)+1; here = ftell(new); rhs.dptr = (char *)&here; --- 467,476 ---- /* make the DBM entry */ *nameend = '\0'; ! if (!violate) ! lhs.dptr = rfc822ize(strsave(line)); ! else ! lhs.dptr = strsave(line); ! *nameend = '\t'; ! lhs.dsize = strlen(lhs.dptr)+1; here = ftell(new); rhs.dptr = (char *)&here; *************** *** 473,477 **** if (ret < 0) fail("dbm failure on `%s'", line); ! *nameend = '\t'; /* and the history entry */ --- 480,484 ---- if (ret < 0) fail("dbm failure on `%s'", line); ! free(lhs.dptr); /* and the history entry */ *************** *** 909,913 **** limit = buf + bsize - len; for (scan = buf; scan < limit; scan++) ! if (TOLOW(*scan) == 's' && cistrncmp(scan, sline, len) == 0 && (scan == buf || *(scan-1) == '\n')) { scan += len; --- 916,920 ---- limit = buf + bsize - len; for (scan = buf; scan < limit; scan++) ! if (CISTREQN(scan, sline, len) && (scan == buf || *(scan-1) == '\n')) { scan += len; *************** *** 915,919 **** if (*limit == '\n') break; ! while (scan < limit && isspace(*scan)) scan++; len = limit-scan; --- 922,926 ---- if (*limit == '\n') break; ! while (scan < limit && isascii(*scan) && isspace(*scan)) scan++; len = limit-scan; *************** *** 1143,1147 **** */ void ! unprivileged() { } --- 1150,1155 ---- */ void ! unprivileged(reason) ! char *reason; { } *** cnpatch/tmp.file Thu Sep 14 15:51:56 1989 --- expire/histinfo.c Mon Sep 11 17:38:15 1989 *************** *** 87,95 **** while ((line = fgetms(in)) != NULL && strcmp(line, "\n") != 0) { line[strlen(line)-1] = '\0'; /* trim newline */ ! if (cistrncmp(line, msgidnm, STRLEN(msgidnm)) == 0) { if (msgid != NULL) free(msgid); msgid = strsave(line+STRLEN(msgidnm)); ! } else if (cistrncmp(line, expnm, STRLEN(expnm)) == 0) { free(expiry); expiry = strsave(line+STRLEN(expnm)); --- 87,95 ---- while ((line = fgetms(in)) != NULL && strcmp(line, "\n") != 0) { line[strlen(line)-1] = '\0'; /* trim newline */ ! if (CISTREQN(line, msgidnm, STRLEN(msgidnm))) { if (msgid != NULL) free(msgid); msgid = strsave(line+STRLEN(msgidnm)); ! } else if (CISTREQN(line, expnm, STRLEN(expnm))) { free(expiry); expiry = strsave(line+STRLEN(expnm)); *************** *** 109,113 **** /* deal with empty and trash articles */ ! if (msgid == NULL || strchr(msgid, '\t') != NULL) { if (msgid != NULL) free(msgid); --- 109,116 ---- /* deal with empty and trash articles */ ! if (msgid == NULL || strchr(msgid, '\t') != NULL || msgid[0] != '<' || ! msgid[strlen(msgid)-1] != '>' || ! strchr(expiry, '\t') != NULL || ! strchr(expiry, '~') != NULL) { if (msgid != NULL) free(msgid); *************** *** 134,138 **** */ void ! unprivileged() { } --- 137,142 ---- */ void ! unprivileged(reason) ! char *reason; { } *** cnpatch/tmp.file Thu Sep 14 15:51:57 1989 --- expire/histslash.c Tue Aug 29 19:24:44 1989 *************** *** 32,36 **** scan++; } ! fputs(line, stdout); free(line); } --- 32,37 ---- scan++; } ! if (fputs(line, stdout) == EOF) ! error("fputs failed", ""); free(line); } *** cnpatch/tmp.file Thu Sep 14 15:51:58 1989 --- expire/mkdbm.c Wed Sep 13 16:36:31 1989 *************** *** 7,12 **** #include <stdio.h> #include <string.h> - #include <ctype.h> #include "fgetmfs.h" --- 7,12 ---- #include <stdio.h> #include <string.h> #include "fgetmfs.h" + #include "case.h" *************** *** 40,43 **** --- 40,44 ---- *scan = '\0'; + rfc822ize(line); lhs.dptr = line; lhs.dsize = strlen(line) + 1; *** cnpatch/tmp.file Thu Sep 14 15:51:59 1989 --- expire/mkhistory Wed Sep 13 20:49:00 1989 *************** *** 8,12 **** umask $NEWSUMASK ! lock="$NEWSCTL/LOCK" # modify name as appropriate ltemp="$NEWSCTL/L.$$" echo $$ >$ltemp --- 8,12 ---- umask $NEWSUMASK ! lock="$NEWSCTL/LOCK" ltemp="$NEWSCTL/L.$$" echo $$ >$ltemp *** cnpatch/tmp.file Thu Sep 14 15:52:00 1989 --- expire/superkludge Wed Sep 13 16:56:22 1989 *************** *** 32,36 **** END { print FILENAME, mid, sup ; exit }' $f >>/tmp/sup$$ done ! awk 'NF > 3 || $2 !~ /^<.*>$/ || $3 !~ /^(<.*>)?$/' /tmp/sup$$ >/tmp/supx$$ if test -s /tmp/supx$$ then --- 32,36 ---- END { print FILENAME, mid, sup ; exit }' $f >>/tmp/sup$$ done ! awk 'NF > 3 || $2 !~ /^<.*>$/ || (NF == 3 && $3 !~ /^(<.*>)?$/)' /tmp/sup$$ >/tmp/supx$$ if test -s /tmp/supx$$ then *** cnpatch/tmp.file Thu Sep 14 15:52:01 1989 --- expire/updatemin.c Tue Sep 5 17:29:35 1989 *************** *** 211,215 **** */ void ! unprivileged() { } --- 211,216 ---- */ void ! unprivileged(reason) ! char *reason; { } *** cnpatch/tmp.file Thu Sep 14 15:52:04 1989 --- h/case.h Sun Aug 27 18:39:49 1989 *************** *** 1,5 **** extern int cistrncmp(); - /* must call the above once before invoking the macro below */ extern char casemap[]; ! #define TOLOW(c) (casemap[(c)]) --- 1,12 ---- extern int cistrncmp(); + extern char *rfc822ize(); extern char casemap[]; ! ! /* must call cistrncmp before invoking TOLOW... */ ! #define TOLOW(c) (casemap[(c)+128]) /* see case.c for why 128 */ ! ! /* ...but the use of it in CISTREQN is safe without the preliminary call (!) */ ! /* CISTREQN is an optimised case-insensitive strncmp(a,b,n)==0; n > 0 */ ! #define CISTREQN(a, b, n) \ ! (TOLOW((a)[0]) == TOLOW((b)[0]) && cistrncmp(a, b, n) == 0) *** cnpatch/tmp.file Thu Sep 14 15:52:05 1989 --- h/libc.h Sat Aug 26 18:34:25 1989 *************** *** 56,61 **** extern FILE *popen(); /* stdio.h */ #ifdef __STDC__ ! extern int printf(char *fmt, ...), fprintf(FILE *, char *fmt, ...); /* stdio.h */ ! extern sprvalue sprintf(char *buf, char *fmt, ...); /* stdio.h */ #else /* __STDC__ */ extern int printf(), fprintf(); /* stdio.h */ --- 56,62 ---- extern FILE *popen(); /* stdio.h */ #ifdef __STDC__ ! extern int printf(char *fmt, ...) /* stdio.h */ ! extern int fprintf(FILE *fp, char *fmt, ...); /* stdio.h */ ! extern sprvalue sprintf(char *buf, char *fmt, ...); /* stdio.h */ #else /* __STDC__ */ extern int printf(), fprintf(); /* stdio.h */ *** cnpatch/tmp.file Thu Sep 14 15:52:11 1989 --- input/newsspool.c Tue Sep 5 17:20:37 1989 *************** *** 285,291 **** */ void ! unprivileged() { setgid(getgid()); setuid(getuid()); } --- 285,294 ---- */ void ! unprivileged(reason) ! char *reason; { setgid(getgid()); setuid(getuid()); + fprintf(stderr, "%s: renouncing setuid due to nonstandard `%s'\n", + progname, reason); } *** cnpatch/tmp.file Thu Sep 14 15:52:26 1989 --- libcnews/case.c Mon Aug 28 14:16:11 1989 *************** *** 5,10 **** * headers are limited to the ASCII characters by RFC822. It is barely * possible that we might be dealing with a translation into another ! * character set, but in particular it's very difficult for a header ! * character to be negative without blowing standard compliance. */ #include <stdio.h> --- 5,13 ---- * headers are limited to the ASCII characters by RFC822. It is barely * possible that we might be dealing with a translation into another ! * character set, but in particular it's very unlikely for a header ! * character to be outside -128..255. ! * ! * Life would be a whole lot simpler if tolower() could safely and portably ! * be applied to any char. */ #include <stdio.h> *************** *** 12,16 **** #include "case.h" ! #define MAPSIZE 256 /* overkill for ASCII */ char casemap[MAPSIZE]; /* relies on init to '\0' */ static int primed = 0; /* has casemap been set up? */ --- 15,21 ---- #include "case.h" ! /* note that case.h knows the value of OFFSET */ ! #define OFFSET 128 /* avoid trouble with negative chars */ ! #define MAPSIZE (256+OFFSET) char casemap[MAPSIZE]; /* relies on init to '\0' */ static int primed = 0; /* has casemap been set up? */ *************** *** 25,28 **** --- 30,34 ---- register char *up; register int c; + register int i; static char lower[] = "abcdefghijklmnopqrstuvwxyz"; static char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; *************** *** 30,39 **** for (lp = lower, up = upper; *lp != '\0'; lp++, up++) { c = *lp; ! casemap[c] = c; ! casemap[*up] = c; } ! for (c = 0; c < MAPSIZE; c++) ! if (casemap[c] == '\0') ! casemap[c] = c; primed = 1; } --- 36,45 ---- for (lp = lower, up = upper; *lp != '\0'; lp++, up++) { c = *lp; ! casemap[c+OFFSET] = c; ! casemap[*up+OFFSET] = c; } ! for (i = 0; i < MAPSIZE; i++) ! if (casemap[i] == '\0') ! casemap[i] = (char)(i-OFFSET); primed = 1; } *************** *** 78,80 **** --- 84,120 ---- else return(TOLOW(*p1) - TOLOW(*p2)); + } + + /* + - rfc822ize - do the bizarre case conversion needed for rfc822 message-ids + */ + char * /* returns the argument */ + rfc822ize(s) + char *s; + { + register char *p; + static char post[] = "postmaster"; + static int postlen = sizeof(post)-1; + + if (!primed) + prime(); + + p = strrchr(s, '@'); + if (p == NULL) /* no local/domain split */ + p = ""; /* assume all local */ + else if (p - (s+1) == postlen && CISTREQN(s+1, post, postlen)) { + /* crazy special case -- "postmaster" is case-insensitive */ + p = s; + } + #ifdef NONSTANDARD + #ifdef RFCVIOLATION + #ifdef B_2_11_MISTAKE + p = s; /* all case-insensitive */ + #endif + #endif + #endif + for (; *p != '\0'; p++) + *p = TOLOW(*p); + + return(s); } *** cnpatch/tmp.file Thu Sep 14 15:52:28 1989 --- libcnews/config.c Tue Sep 5 17:17:40 1989 *************** *** 61,67 **** { register char *p; - register int nonstd = NO; register int mask; register char *scan; if (dirsset) --- 61,68 ---- { register char *p; register int mask; register char *scan; + register int ns = 0; + # define NONSTD(reason) { if (!ns) { unprivileged(reason); ns = 1; } } if (dirsset) *************** *** 70,75 **** p = getenv("NEWSARTS"); if (p != NULL && !STREQ(p, arts)) { - nonstd = YES; arts = p; } --- 71,76 ---- p = getenv("NEWSARTS"); if (p != NULL && !STREQ(p, arts)) { arts = p; + NONSTD("NEWSARTS"); } *************** *** 77,81 **** if (p != NULL && !STREQ(p, ctl)) { ctl = p; ! nonstd = YES; } --- 78,82 ---- if (p != NULL && !STREQ(p, ctl)) { ctl = p; ! NONSTD("NEWSCTL"); } *************** *** 83,87 **** if (p != NULL && !STREQ(p, path)) { path = p; ! nonstd = YES; } --- 84,88 ---- if (p != NULL && !STREQ(p, path)) { path = p; ! NONSTD("NEWSPATH"); } *************** *** 89,93 **** if (p != NULL && !STREQ(p, bin)) { bin = p; ! nonstd = YES; } --- 90,94 ---- if (p != NULL && !STREQ(p, bin)) { bin = p; ! NONSTD("NEWSBIN"); } *************** *** 104,108 **** if (mask != numask) { numask = mask; ! nonstd = YES; } } --- 105,109 ---- if (mask != numask) { numask = mask; ! NONSTD("NEWSUMASK"); } } *************** *** 111,120 **** if (p != NULL && !STREQ(p, nmaster)) { nmaster = p; ! nonstd = YES; } dirsset = YES; - if (nonstd) - unprivileged(); } --- 112,119 ---- if (p != NULL && !STREQ(p, nmaster)) { nmaster = p; ! NONSTD("NEWSMASTER"); } dirsset = YES; } *** cnpatch/tmp.file Thu Sep 14 15:52:48 1989 --- libstdio/fgets.c Wed Sep 6 16:33:39 1989 *************** *** 30,33 **** --- 30,35 ---- register int bytesleft = fp->_cnt; /* to EOB */ + if (bytesleft < 0) + bytesleft = 0; if (bytesleft > lim) /* buffer longer than s */ bytesleft = lim; /* only copy to s's end */ *** cnpatch/tmp.file Thu Sep 14 15:52:50 1989 --- libstdio/rdwr.c Wed Sep 6 16:33:38 1989 *************** *** 29,32 **** --- 29,34 ---- register int copy = fp->_cnt; + if (copy < 0) + copy = 0; if (copy > bytes) /* buffer longer than ptr */ copy = bytes; /* only fill ptr */ *************** *** 76,79 **** --- 78,83 ---- register int copy = fp->_cnt; + if (copy < 0) + copy = 0; if (copy > bytes) /* buffer longer than ptr */ copy = bytes; /* only empty ptr */ *** cnpatch/tmp.file Thu Sep 14 15:53:01 1989 --- man/expire.8 Thu Sep 14 15:50:22 1989 *************** *** 7,11 **** .\" =()<.ds m @<NEWSMASTER>@>()= .ds m usenet ! .TH EXPIRE 8 "23 Aug 1989" "C News" .SH NAME expire, doexpire \- expire old news --- 7,11 ---- .\" =()<.ds m @<NEWSMASTER>@>()= .ds m usenet ! .TH EXPIRE 8 "13 Sept 1989" "C News" .SH NAME expire, doexpire \- expire old news *************** *** 15,18 **** --- 15,20 ---- upact \- update news active file .br + recovact \- partially recover news active file + .br superkludge \- implement stupid Supersedes header in news .SH SYNOPSIS *************** *** 53,56 **** --- 55,60 ---- .B \*b/expire/upact .br + .B \*b/expire/recovact + .br .B \*b/expire/superkludge [ *************** *** 226,230 **** updates the third fields of the \fIactive\fR file to match the articles in \fI\*a\fR (for historical reasons, \fIexpire\fR does not do this). ! These programs are both fairly slow and they both lock the whole news system for the duration of the run, so they should not be run casually. .PP --- 230,238 ---- updates the third fields of the \fIactive\fR file to match the articles in \fI\*a\fR (for historical reasons, \fIexpire\fR does not do this). ! .I Recovact ! updates the second fields of the \fIactive\fR file to match the articles ! in \fI\*a\fR, ! for use in disaster recovery based on an outdated \fIactive\fR file. ! These programs are all fairly slow and they all lock the whole news system for the duration of the run, so they should not be run casually. .PP *************** *** 266,270 **** `Supersedes' header. .PP ! Some of the more obscure options of \fIexpire\fR have not been tested well. .PP One cannot put more than one newsgroup into a single archiving directory --- 274,280 ---- `Supersedes' header. .PP ! .I Superkludge ! does not understand RFC822's complex case-sensitivity rules for message-IDs, ! and insists on an exact case-sensitive match. .PP One cannot put more than one newsgroup into a single archiving directory *** cnpatch/tmp.file Thu Sep 14 15:53:03 1989 --- man/inews.1 Tue Aug 29 12:20:37 1989 *************** *** 7,11 **** .\" =()<.ds m @<NEWSMASTER>@>()= .ds m usenet ! .TH INEWS 1 "6 Aug 1989" "C News" .SH NAME inews \- `user-friendly' news-posting front-end for relaynews --- 7,11 ---- .\" =()<.ds m @<NEWSMASTER>@>()= .ds m usenet ! .TH INEWS 1 "29 Aug 1989" "C News" .SH NAME inews \- `user-friendly' news-posting front-end for relaynews *************** *** 117,124 **** .PP .B "inews -p" is exactly equivalent to invoking ! .BR rnews (8); ! this is seldom useful in C News. Normal usage is .BR "inews -h" , --- 117,133 ---- .PP .B "inews -p" + .I files is exactly equivalent to invoking ! .B "cat" ! .I files ! .BR "| relaynews -r" , ! where ! .I files ! may be an empty list; ! there is no automatic recovery of the input ! file(s) in case of errors, ! full disks ! or other problems. Normal usage is .BR "inews -h" , *************** *** 209,212 **** --- 218,224 ---- (no line-printer graphics, please) .TP + .IB $HOME /dead.article + saved article in case of errors or problems + .TP .BR /tmp/in * temporaries *************** *** 214,219 **** .SH "SEE ALSO" .IR mail (1), ! .IR rnews (1), ! .IR newsaux (8) .SH DIAGNOSTICS .I inews --- 226,232 ---- .SH "SEE ALSO" .IR mail (1), ! .IR news (5), ! .IR newsaux (8), ! .IR relaynews (8) .SH DIAGNOSTICS .I inews *** cnpatch/tmp.file Thu Sep 14 15:53:04 1989 --- man/newsaux.8 Wed Sep 13 20:49:45 1989 *************** *** 7,11 **** .\" =()<.ds m @<NEWSMASTER>@>()= .ds m usenet ! .TH NEWSAUX 8 "19 Aug 1989" "C News" .SH NAME spacefor \- check available space for news --- 7,11 ---- .\" =()<.ds m @<NEWSMASTER>@>()= .ds m usenet ! .TH NEWSAUX 8 "13 Sept 1989" "C News" .SH NAME spacefor \- check available space for news *************** *** 21,24 **** --- 21,26 ---- gngp \- search text using a newsgroup pattern .br + canonhdr \- extract header and canonicalize case in header keywords + .br newshist \- extract history line for news article(s) .br *************** *** 57,63 **** --- 59,70 ---- [ .B \-a + ] [ + .B \-r ] ngpattern file ... .br + .B \*b/canonhdr + [ file ] ... + .br .B \*b/maint/newshist msgid ... *************** *** 133,136 **** --- 140,156 ---- flag is given, the eligible substrings start at the beginning of the line and end at white space or the end of the line. + The + \fB\-r\fR flag reverses the inputs, with patterns coming from + the file and the argument taken as the line(s). + .PP + .I Canonhdr + takes the concatenation of its input \fIfile\fR(s) (standard input if none) + as an article, + and outputs the header from the article with header keywords canonicalized + for easier processing. + Canonicalization forces all alphabetics to lower case except the first + letter of the keyword, which is forced to upper case. + (One exception: + ``Message-ID'' is the canonical form of [e.g.] ``message-id''.) .PP .I Newshist *** cnpatch/tmp.file Thu Sep 14 15:53:06 1989 --- man/newsbatch.8 Wed Sep 13 16:12:45 1989 *************** *** 7,11 **** .\" =()<.ds m @<NEWSMASTER>@>()= .ds m usenet ! .TH NEWSBATCH 8 "19 Aug 1989" "C News" .SH NAME sendbatches, batchsplit \- news batching to other sites --- 7,11 ---- .\" =()<.ds m @<NEWSMASTER>@>()= .ds m usenet ! .TH NEWSBATCH 8 "26 Aug 1989" "C News" .SH NAME sendbatches, batchsplit \- news batching to other sites *************** *** 17,21 **** c7encode, bencode \- compressed-news-batch encoding .br ! viauux, viauuxz, viainews \- news-batch transmission .br viamail, viaemail, viapmail \- news-batch transmission via mail --- 17,21 ---- c7encode, bencode \- compressed-news-batch encoding .br ! viauux, viauuxz, viainews, viarsh \- news-batch transmission .br viamail, viaemail, viapmail \- news-batch transmission via mail *************** *** 72,75 **** --- 72,78 ---- site .br + .B \&.../viarsh + site + .br .B \&.../viamail site *************** *** 216,219 **** --- 219,227 ---- feed the batch back to \fIinews\fR, ignoring the \fIsite\fR argument (normally useful only for ihave/sendme) + .IP viarsh + use \fIrsh\fR to run \fIrnews\fR on the \fIsite\fR via Ethernet, + Internet, etc. + (the directory containing \fIrnews\fR + must be in the default PATH on \fIsite\fR) .IP viamail mail the batch to \fIsite\fB!rnews\fR *** cnpatch/tmp.file Thu Sep 14 15:53:09 1989 --- misc/Makefile Tue Aug 29 12:18:05 1989 *************** *** 13,17 **** MAINTBIN=newshist MAINT = $(MAINTBIN) newsdaily newswatch newsboot locknews addgroup delgroup adddirs ! UTILBIN = gngp newslock ctime getdate UTILS = $(UTILBIN) sizeof newshostname THEM = $(MAINT) $(UTILS) --- 13,17 ---- MAINTBIN=newshist MAINT = $(MAINTBIN) newsdaily newswatch newsboot locknews addgroup delgroup adddirs ! UTILBIN = gngp newslock ctime getdate canonhdr UTILS = $(UTILBIN) sizeof newshostname THEM = $(MAINT) $(UTILS) *************** *** 45,48 **** --- 45,51 ---- newslock: newslock.o $(LIBS) $(CC) $(CFLAGS) $(LDFLAGS) newslock.o $(PRE) $(LIBS) $(POST) -o $@ + + canonhdr: canonhdr.o $(LIBS) + $(CC) $(CFLAGS) $(LDFLAGS) canonhdr.o $(PRE) $(LIBS) $(POST) -o $@ NHCFLAGS = -I$(RN) $(CFLAGS) *** cnpatch/tmp.file Thu Sep 14 15:53:13 1989 --- misc/gngp.c Wed Sep 6 16:29:05 1989 *************** *** 1,4 **** /* ! * gngp - globally find newsgroup and print * like grep, but for newsgroup patterns instead of regular expressions */ --- 1,4 ---- /* ! * gngp - globally match newsgroup pattern and print * like grep, but for newsgroup patterns instead of regular expressions */ *************** *** 13,16 **** --- 13,17 ---- */ int anchored = 0; + int reverse = 0; /* iff true, reverse argument & file roles */ FILE *efopen(); *************** *** 30,34 **** progname = argv[0]; ! while ((c = getopt(argc, argv, "ad")) != EOF) switch (c) { case 'a': /* anchored at start of line */ --- 31,35 ---- progname = argv[0]; ! while ((c = getopt(argc, argv, "adr")) != EOF) switch (c) { case 'a': /* anchored at start of line */ *************** *** 39,42 **** --- 40,46 ---- debug++; break; + case 'r': /* reverse roles: ngs in arg., patterns in file */ + reverse++; + break; default: errflg++; *************** *** 44,48 **** } if (errflg || optind == argc) { ! (void) fprintf(stderr, "usage: %s [-ad] pattern [file...]\n", progname); exit(2); --- 48,52 ---- } if (errflg || optind == argc) { ! (void) fprintf(stderr, "usage: %s [-adr] ng_pattern [file...]\n", progname); exit(2); *************** *** 102,106 **** } } ! returned = ngmatch(pattern, text); if (anchored) { if (whitesp != NULL) --- 106,110 ---- } } ! returned = (!reverse? ngmatch(pattern, text): ngmatch(text, pattern)); if (anchored) { if (whitesp != NULL) *** cnpatch/tmp.file Thu Sep 14 15:53:27 1989 --- notebook/config Tue Sep 5 17:31:30 1989 *************** *** 1,3 **** ! .DA "18 Feb 1989" .TL Configuration Mechanisms in C News --- 1,3 ---- ! .DA "5 Sept 1989" .TL Configuration Mechanisms in C News *************** *** 93,100 **** .LP .RS ! .IP "void unprivileged(void);" Drop any special powers that should not be available to a normal user program, e.g. those obtained by set-uid bit. .RE .LP --- 93,102 ---- .LP .RS ! .IP "void unprivileged(char *reason);" Drop any special powers that should not be available to a normal user program, e.g. those obtained by set-uid bit. + .I Reason + is the name of the first environment variable that caused trouble. .RE .LP *** cnpatch/tmp.file Thu Sep 14 15:53:42 1989 --- relay/aux/chamod Tue Sep 12 12:53:54 1989 *************** *** 19,26 **** esac ! aflag=`awk "/$1/"' { print $4 }' $NEWSCTL/active` if test "$aflag" != "$flag" -a \( "$aflag" = m -o "$aflag" = y \); then # old & new flags differ & old flag is m or y - # watch closely - shell quoting is tricky here awk ' $1 == "'$1'" { # this line is for first arg. --- 19,26 ---- esac ! # watch closely - shell quoting is tricky in the next two awk invocations ! aflag=`awk '$1 == "'$1'" { print $4 }' $NEWSCTL/active` if test "$aflag" != "$flag" -a \( "$aflag" = m -o "$aflag" = y \); then # old & new flags differ & old flag is m or y awk ' $1 == "'$1'" { # this line is for first arg. *** cnpatch/tmp.file Thu Sep 14 15:53:46 1989 --- relay/aux/newsreply Tue Aug 29 12:16:17 1989 *************** *** 10,23 **** umask $NEWSUMASK ! art=/tmp/nc$$ mroute=/tmp/ncm$$ ! cat >$art if test -r $NEWSCTL/replyusepath then ! sender="`grep '^Path:' $art | sed 's/^[^:]*://' `" ! echo "$sender" ! rm -f $art exit 0 fi --- 10,22 ---- umask $NEWSUMASK ! hdr=/tmp/nc$$ mroute=/tmp/ncm$$ ! canonhdr >$hdr if test -r $NEWSCTL/replyusepath then ! grep '^Path:' $hdr | sed 's/^[^:]*:[ ]*//' ! rm -f $hdr exit 0 fi *************** *** 24,30 **** # pick out the appropriate header ! sender="` grep '^Reply-To:' $art `" case "$sender" in ! "") sender="` grep '^From:' $art `" ;; esac --- 23,29 ---- # pick out the appropriate header ! sender="` grep '^Reply-To:' $hdr `" case "$sender" in ! "") sender="` grep '^From:' $hdr `" ;; esac *************** *** 55,57 **** fi ! rm -f $art $mroute --- 54,56 ---- fi ! rm -f $hdr $mroute *** cnpatch/tmp.file Thu Sep 14 15:53:51 1989 --- relay/ctl/checkgroups Wed Sep 13 13:18:50 1989 *************** *** 19,26 **** sort -u -o $NEWSCTL/newsgroups $NEWSCTL/newsgroups.bac # generate list of approved newsgroups from $nl/newsgroups - # [^.]*\. in next two egreps was net.|mod.|fa., which is inadequate - geoff (echo junk; echo control; sed 's/[ \ ].*//' $NEWSCTL/newsgroups | ! egrep "^([^.]*\.|general)") | sort -u >/tmp/$$a # generate list of locally-present newsgroups from $nl/active --- 19,36 ---- sort -u -o $NEWSCTL/newsgroups $NEWSCTL/newsgroups.bac + # locate our subscription list + me="`newshostname`" + gngppat=`awk -f $NEWSBIN/relay/canonsys.awk $NEWSCTL/sys | + egrep "^($me|ME):" | + awk -F: ' + { + fields = split($2, field2, "/") # split ngs/dists + print field2[1] # print only ngs + exit + }' ` + # generate list of approved newsgroups from $nl/newsgroups (echo junk; echo control; sed 's/[ \ ].*//' $NEWSCTL/newsgroups | ! egrep "^([^.]*\.|general)") | gngp -a "$gngppat" | sort -u >/tmp/$$a # generate list of locally-present newsgroups from $nl/active *** cnpatch/tmp.file Thu Sep 14 15:53:52 1989 --- relay/ctl/newgroup Tue Aug 29 12:16:19 1989 *************** *** 9,23 **** umask $NEWSUMASK ! F=/tmp/nc$$ ! trap "rm -f $F; exit 0" 0 ! cat >$F # unapproved ctl msg? then quit ! grep -s '^Approved:' $F >/dev/null || { rm -f $F; exit 0; } ! SENDER="`grep '^Sender:' $F | sed 's/^[^:]*: *//'`" case "$SENDER" in ! "") SENDER="`grep '^From:' $F | sed 's/^[^:]*: *//' `" ;; esac --- 9,23 ---- umask $NEWSUMASK ! hdr=/tmp/nc$$ ! trap "rm -f $hdr; exit 0" 0 ! canonhdr >$hdr # unapproved ctl msg? then quit ! grep -s '^Approved:' $hdr >/dev/null || { rm -f $hdr; exit 0; } ! SENDER="`grep '^Sender:' $hdr | sed 's/^[^:]*: *//'`" case "$SENDER" in ! "") SENDER="`grep '^From:' $hdr | sed 's/^[^:]*: *//' `" ;; esac *** cnpatch/tmp.file Thu Sep 14 15:53:53 1989 --- relay/ctl/rmgroup Tue Aug 29 12:16:20 1989 *************** *** 8,27 **** umask $NEWSUMASK ! F=/tmp/nc$$ ! cat >$F # unapproved ctl msg? then quit ! egrep '^Approved:' $F >/dev/null || { rm -f $F; exit 0; } # quit if no active entry egrep "^`echo $1 | sed 's/\./\\\\./g'` " $NEWSCTL/active >/dev/null || ! { rm -f $F; exit 0; } ! SENDER="`grep '^Sender:' $F | sed 's/^[^:]*: *//'`" case "$SENDER" in ! "") ! SENDER="`grep '^From:' $F | sed 's/^[^:]*: *//'`" ! ;; esac --- 8,25 ---- umask $NEWSUMASK ! hdr=/tmp/nc$$ ! canonhdr >$hdr # unapproved ctl msg? then quit ! egrep '^Approved:' $hdr >/dev/null || { rm -f $hdr; exit 0; } # quit if no active entry egrep "^`echo $1 | sed 's/\./\\\\./g'` " $NEWSCTL/active >/dev/null || ! { rm -f $hdr; exit 0; } ! SENDER="`grep '^Sender:' $hdr | sed 's/^[^:]*: *//'`" case "$SENDER" in ! "") SENDER="`grep '^From:' $hdr | sed 's/^[^:]*: *//'`" ;; esac *************** *** 29,31 **** echo "rmgroup $1 says $SENDER" | mail $NEWSMASTER ! rm -f $F* --- 27,29 ---- echo "rmgroup $1 says $SENDER" | mail $NEWSMASTER ! rm -f $hdr *** cnpatch/tmp.file Thu Sep 14 15:54:01 1989 --- relay/hdrmunge.c Tue Aug 29 12:18:03 1989 *************** *** 22,25 **** --- 22,26 ---- #include "libc.h" #include "news.h" + #include "case.h" #include "fileart.h" #include "headers.h" *************** *** 92,98 **** if (headdebug) (void) fputs(buffer, stderr); ! for (vhp = hdrlst; *vhp != NULL; vhp++) ! if (STREQN(buffer, (*vhp)->hdrnm, (int)(*vhp)->hdrlen)) return; /* don't save this header */ hdrsave(art, buffer, hdrlen); } --- 93,102 ---- if (headdebug) (void) fputs(buffer, stderr); ! for (vhp = hdrlst; *vhp != NULL; vhp++) { ! register char *hdrnm = (*vhp)->hdrnm; ! ! if (CISTREQN(buffer, hdrnm, (int)(*vhp)->hdrlen)) return; /* don't save this header */ + } hdrsave(art, buffer, hdrlen); } *************** *** 172,176 **** register int hdrlen; { ! if (STREQN(hdr, pathhdr.hdrnm, (int)pathhdr.hdrlen)) { register char *oldpath, *hostnm = hostname(); --- 176,180 ---- register int hdrlen; { ! if (CISTREQN(hdr, pathhdr.hdrnm, (int)pathhdr.hdrlen)) { register char *oldpath, *hostnm = hostname(); *** cnpatch/tmp.file Thu Sep 14 15:54:05 1989 --- relay/hdrparse.c Tue Aug 29 12:18:04 1989 *************** *** 4,11 **** #include <stdio.h> - #include <ctype.h> #include <sys/types.h> #include "libc.h" #include "news.h" #include "headers.h" #include "hdrint.h" --- 4,11 ---- #include <stdio.h> #include <sys/types.h> #include "libc.h" #include "news.h" + #include "case.h" #include "headers.h" #include "hdrint.h" *************** *** 22,30 **** /* ! * Parse RFC822/850/1036 header into "hdrs". Retain significant values. ! * Assumes ishdr has been called first. ! * ! * If a keyword matches one in hdrlst, store the value in *malloc'ed memory* ! * (N.B.). freeheader() will free this memory. */ void --- 22,31 ---- /* ! * Parse (assumed) RFC822/850/1036 header in "line" (ishdr(line) can ! * verify this) into "hdrs" using hdrlst set of keywords by retaining the ! * value of any matching keyword. Keyword matching is case-insensitive. ! * If the keyword in "line" matches one in hdrlst, store the value in ! * *malloc'ed memory* (N.B.) pointed to by a member of "hdrs". ! * freeheader() will free this memory. */ void *************** *** 36,51 **** register struct hdrdef **hpp; ! for (hpp = hdrlst; *hpp != NULL; hpp++) ! if (STREQN(line, (*hpp)->hdrnm, (int)(*hpp)->hdrlen) && ! (*hpp)->hdroff >= 0) { /* paranoia */ ! register char **ptrp = ! (char **)((char *)hdrs+(*hpp)->hdroff); ! nnfree(ptrp); /* free prev. val. in this art. */ ! *ptrp = strsave(skipsp(&line[(*hpp)->hdrlen])); ! if (*ptrp != NULL) ! trim(*ptrp); /* cut trailing \n */ break; ! } } --- 37,55 ---- register struct hdrdef **hpp; ! for (hpp = hdrlst; *hpp != NULL; hpp++) { ! register char *hdrnm = (*hpp)->hdrnm; ! if (CISTREQN(line, hdrnm, (int)(*hpp)->hdrlen) && ! (*hpp)->hdroff >= 0) /* paranoia */ break; ! } ! if (*hpp != NULL) { ! register char **ptrp = (char **)((char *)hdrs+(*hpp)->hdroff); ! ! nnfree(ptrp); /* free prev. value in this article */ ! *ptrp = strsave(skipsp(&line[(*hpp)->hdrlen])); ! if (*ptrp != NULL) ! trim(*ptrp); /* cut trailing \n */ ! } } *** cnpatch/tmp.file Thu Sep 14 15:54:08 1989 --- relay/history.c Wed Sep 6 16:28:09 1989 *************** *** 23,26 **** --- 23,27 ---- #include "libc.h" #include "news.h" + #include "case.h" #include "config.h" #include "fgetmfs.h" *************** *** 101,105 **** if (!openhist()) return msgidkey; ! clnmsgid = strsave(msgid); sanitise(clnmsgid); msgidkey.dptr = clnmsgid; --- 102,106 ---- if (!openhist()) return msgidkey; ! clnmsgid = rfc822ize(strsave(msgid)); sanitise(clnmsgid); msgidkey.dptr = clnmsgid; *************** *** 233,243 **** fulldisk(art, filename); ! msgidkey.dptr = msgid; msgidkey.dsize = strlen(msgid) + 1; /* include NUL */ posdatum.dptr = (char *)&pos; posdatum.dsize = sizeof pos; ! #ifdef NOSTOREVAL ! /* original v7 dbm store() returned no value */ ! (void) store(msgidkey, posdatum); #else if (store(msgidkey, posdatum) < 0) --- 234,243 ---- fulldisk(art, filename); ! msgidkey.dptr = rfc822ize(strsave(msgid)); msgidkey.dsize = strlen(msgid) + 1; /* include NUL */ posdatum.dptr = (char *)&pos; posdatum.dsize = sizeof pos; ! #ifdef NOSTOREVAL /* original v7 dbm store() returned no value */ ! store(msgidkey, posdatum); #else if (store(msgidkey, posdatum) < 0) *************** *** 244,247 **** --- 244,248 ---- fulldisk(art, filename); #endif + free(msgidkey.dptr); } *** cnpatch/tmp.file Thu Sep 14 15:54:14 1989 --- relay/makefile Wed Sep 13 20:48:34 1989 *************** *** 76,80 **** cp aux/* $(NEWSBIN)/relay rm -f $(BIN)/inews ! ln $(NEWSBIN)/inject/inews $(BIN)/inews || cp sh/inews $(BIN) cmp: relaynews --- 76,80 ---- cp aux/* $(NEWSBIN)/relay rm -f $(BIN)/inews ! ln $(NEWSBIN)/inject/inews $(BIN)/inews 2>/dev/null || cp sh/inews $(BIN) cmp: relaynews *** cnpatch/tmp.file Thu Sep 14 15:54:20 1989 --- relay/procart.c Wed Sep 6 16:34:22 1989 *************** *** 214,218 **** art->a_charswritten += bodylen; } ! for (; art->a_unread > 0 && !(art->a_status&ST_DISKFULL) && (readcnt=fread(block, 1, (int)min(art->a_unread, COPYSIZE), in)) > 0; art->a_unread -= readcnt, art->a_charswritten += readcnt) --- 214,218 ---- art->a_charswritten += bodylen; } ! for (; art->a_unread > 0 && !(art->a_status&ST_DISKFULL) && !feof(in) && (readcnt=fread(block, 1, (int)min(art->a_unread, COPYSIZE), in)) > 0; art->a_unread -= readcnt, art->a_charswritten += readcnt) *** cnpatch/tmp.nonexistent.file.with.very.long.name.for.stupid.patch Thu Sep 14 15:54:41 1989 --- relay/regress/out/stderr Wed Sep 13 20:35:17 1989 *************** *** 0 **** --- 1 ---- + ./relaynews: warning: renouncing setuid due to nonstandard `NEWSARTS' *** cnpatch/tmp.file Thu Sep 14 15:54:45 1989 --- relay/relaynews.c Wed Sep 6 16:25:32 1989 *************** *** 250,257 **** } void ! unprivileged() /* called if NEWSARTS, NEWSCTL or NEWSBIN present */ { userealids = YES; } --- 250,267 ---- } + /* + * called if NEWSARTS, NEWSCTL, NEWSBIN, etc. are non-standard. + * this may be due to legitimate testing, but we can't tell. + * the error message will at least be seen by a human trying to + * track down a problem, even if stderr isn't normally seen. + */ void ! unprivileged(reason) ! char *reason; { userealids = YES; + (void) fprintf(stderr, + "%s: warning: renouncing setuid due to nonstandard `%s'\n", + progname, reason); } *** cnpatch/tmp.file Thu Sep 14 15:54:47 1989 --- relay/sh/anne.jones Fri Sep 8 13:20:58 1989 *************** *** 110,115 **** # strip invisible chars, a la B news; turn tabs to spaces (RFC1036) case "$trversion" in ! v7) tr -d '\1-\7\13\14\16-\37';; ! v6) tr -d '[\1-\7]\13\14[\16-\37]' ;; esac | sed 's/: /: /' | --- 110,115 ---- # strip invisible chars, a la B news; turn tabs to spaces (RFC1036) case "$trversion" in ! v7) tr -d '\1-\7\13\15-\37' ;; ! v6) tr -d '[\1-\7]\13[\15-\37]' ;; esac | sed 's/: /: /' | *** cnpatch/tmp.file Thu Sep 14 15:54:48 1989 --- relay/sh/ctlrun Tue Aug 29 12:16:21 1989 *************** *** 14,23 **** for file in * do ! grep '^Control:' $file | ! sed 's;^Control:[ ]*;'$NEWSBIN/ctl/';' | ! grep -v '/cancel ' >/tmp/ctl$$ # cancel needs dbm(3) sh -x /tmp/ctl$$ <$file done ! rm -f /tmp/ctl$$ ! rm -f LOCK --- 14,23 ---- for file in * do ! # cancel, ihave and sendme are internal to relaynews and use < > metachars. ! canonhdr $file | ! sed -n 's;^Control:[ ]*;'$NEWSBIN/ctl/';p' | ! egrep -v '/(cancel|ihave|sendme) ' >/tmp/ctl$$ sh -x /tmp/ctl$$ <$file done ! rm -f /tmp/ctl$$ LOCK *** cnpatch/tmp.file Thu Sep 14 15:54:49 1989 --- relay/sh/inews Fri Sep 8 13:20:58 1989 *************** *** 39,43 **** -p) shift ! exec rnews $* # rnews, bailing out at or near line 1 ;; esac --- 39,44 ---- -p) shift ! cat $* | relaynews -r # feed directly to relaynews, seat belts off ! exit ;; esac *************** *** 159,162 **** --- 160,167 ---- trap "$cleanup" 0 tear /tmp/in$$ <$input # output in $inhdrs and $inbody + # canonicalise header keyword capitalisation. + # greps for Control: and Approved: later assume this, as does defhdrs.awk. + canonhdr <$inhdrs >/tmp/in$$realtmp + mv /tmp/in$$realtmp $inhdrs # pad zero-line articles, since old B [ir]news are confused by them # and the news readers generate zero-line control messages, alas. *************** *** 184,191 **** # echo Lines: $lines ! # strip invisible chars from body, a la B news case "$trversion" in ! v7) tr -d '\1-\7\13\14\16-\37' ;; ! v6) tr -d '[\1-\7]\13\14[\16-\37]' ;; esac <$inbody --- 189,196 ---- # echo Lines: $lines ! # strip invisible chars from body, a la B news. bells and escapes are right out. case "$trversion" in ! v7) tr -d '\1-\7\13\15-\37' ;; ! v6) tr -d '[\1-\7]\13[\15-\37]' ;; esac <$inbody *************** *** 234,265 **** m) if grep -s '^Approved:[ ]' $inhdrs >/dev/null; then ! rm -f $modroute # just post normally else ! # un-Approved: mail it to the moderator(s). ! echo "%s" >$modroute # in case no route ! # look for route for this group ! cat $NEWSCTL/mailpaths | ! while read ngpat route junk ! do ! # a dreadful B 2.11 hack: ! # backbone == all ! case "$ngpat" in ! backbone) ngpat="all" ;; ! esac ! if gngp -a "$ngpat" $nglist >/dev/null; then ! echo "$route" >$modroute ! break # take only 1st match ! fi ! done ! fi ! # ngpat and route are not set here, damn it! ! if test -s $modroute; then ! # an unapproved article in a mod group: ! # mail the article to this moderator. ! moderator=` ! sed "s/%s/\` echo $ng | tr . - \`/" $modroute ! ` echo "$0: mailing your article to $moderator" >&2 ! mail $moderator <$censart trap 0 # this is a child process - no cleanup here echo 0 >$exitflag --- 239,257 ---- m) if grep -s '^Approved:[ ]' $inhdrs >/dev/null; then ! : # just post normally else ! # un-Approved article: mail it to the moderator(s). ! # look for a route for this group. ! # a dreadful B 2.11 hack: backbone == all ! (sed 's/^backbone[ ]/all /' \ ! $NEWSCTL/mailpaths | ! gngp -a -r "`cat $nglist`"; ! echo 'default %s') | ! sed -n "1{s/^[^ ]*[ ][ ]*// ! s/%s/` echo $ng | tr . - `/p;q;}" \ ! >$modroute ! moderator="`cat $modroute `" echo "$0: mailing your article to $moderator" >&2 ! mail "$moderator" <$censart trap 0 # this is a child process - no cleanup here echo 0 >$exitflag *************** *** 335,341 **** ;; *) ! status=`rsh $server \ ! "PATH=$PATH relaynews $relayopts -s $exclusion -d \"$debug\"; echo status $?" \ ! <$censart >$outfile; sed -n '/^status /s///p' $outfile ` sed '/^status /d' $outfile # print relaynews's stdout ;; --- 327,342 ---- ;; *) ! # send article+commands to remote shell, including clean up ! (echo "sed 's/^-//' >/tmp/irsh\$\$ <<'!'" # remove guard ! sed 's/^[^A-EG-Za-z0-9]/-&/' $censart # prepend guard ! echo ! ! cat <<! ! PATH=$PATH relaynews $relayopts -s $exclusion -d "$debug" </tmp/irsh\$\$ ! ! ! echo 'echo status $?' ! echo 'rm -f /tmp/irsh$$') | ! rsh $server /bin/sh >$outfile ! ! status=`sed -n '/^status /s///p' $outfile ` sed '/^status /d' $outfile # print relaynews's stdout ;; Files that are new: new batch/viarsh (patch can't create, so diff against null): Index: batch/viarsh *** cnpatch/tmp.preposterously.long.name.to.make.patch.behave.right Thu Sep 14 15:51:06 1989 --- batch/viarsh Sat Aug 26 22:48:03 1989 *************** *** 0 **** --- 1,5 ---- + #! /bin/sh + # Transmit batch to $1 by rshing rnews. This does assume that rnews is + # in a user-searched directory. + + exec rsh $1 rnews new expire/recovact (patch can't create, so diff against null): Index: expire/recovact *** cnpatch/tmp.preposterously.long.name.to.make.patch.behave.right Thu Sep 14 15:51:06 1989 --- expire/recovact Thu Sep 14 15:50:17 1989 *************** *** 0 **** --- 1,62 ---- + #! /bin/sh + # Try to recover 2nd field of active file. + + # =()<. ${NEWSCONFIG-@<NEWSCONFIG>@}>()= + . ${NEWSCONFIG-/usr/lib/news/bin/config} + + PATH=$NEWSCTL/bin:$NEWSBIN/expire:$NEWSBIN:$NEWSPATH ; export PATH + umask $NEWSUMASK + + cd $NEWSCTL || { echo "$0: can't cd to $NEWSCTL" >&2; exit 1; } + + # check active file format + set ""`sed 1q active` + case $# in + 4) ;; + *) echo "$0: active file has other than 4 fields" >&2 + exit 1 ;; + esac + + # lock news system + lock="$NEWSCTL/LOCK" + ltemp="$NEWSCTL/L.$$" + echo $$ >$ltemp + trap "rm -f $ltemp ; exit 0" 0 1 2 15 + while true + do + if newslock $ltemp $lock + then + trap "rm -f $ltemp $lock ; exit 0" 0 1 2 15 + break + fi + sleep 30 + done + + while read group max min fourth + do + dir=`echo $group | tr . / ` # map ng name to directory name + new= + if test -d $NEWSARTS/$dir + then + new=`ls $NEWSARTS/$dir | egrep '^[0-9]+$' | sort -n | tail -1` + fi + case "$new" in + "") new=$max ;; # no files -- preserve old value + *) if test "$new" -lt "$max" # old value more recent (!) + then + new="$max" + fi + ;; + esac + dots="`echo $max | tr 0123456789 ..........`" + max="`expr 0000000000$new : '.*\('$dots'\)$'`" # preserve length + + echo $group $max $min $fourth + done <active >active.new + + # replace active, carefully + rm -f active.old + ln active active.old + mv active.new active + + exit 0 new misc/canonhdr.c (patch can't create, so diff against null): Index: misc/canonhdr.c *** cnpatch/tmp.preposterously.long.name.to.make.patch.behave.right Thu Sep 14 15:51:06 1989 --- misc/canonhdr.c Tue Aug 29 12:18:06 1989 *************** *** 0 **** --- 1,93 ---- + /* + * canonhdr - canonicalise capitalisation of header keywords + */ + + #include <stdio.h> + #include <ctype.h> + #include <sys/types.h> + #include "news.h" + #include "libc.h" + + char *progname; + int debug; + + /* + * main - parse arguments and handle options + */ + main(argc, argv) + int argc; + char *argv[]; + { + int c; + int errflg = 0; + extern int optind; + extern char *optarg; + extern FILE *efopen(); + + progname = argv[0]; + while ((c = getopt(argc, argv, "d")) != EOF) + switch (c) { + case 'd': + ++debug; + break; + default: + errflg++; + break; + } + if (errflg) { + (void) fprintf(stderr, "usage: %s [-d] [file]...\n", progname); + exit(2); + } + + if (optind >= argc) + process(stdin, "stdin"); + else + for (; optind < argc; optind++) + if (STREQ(argv[optind], "-")) + process(stdin, "-"); + else { + FILE *in = efopen(argv[optind], "r"); + + process(in, argv[optind]); + (void) fclose(in); + } + exit(0); + } + + /* + * process - process input file + */ + process(in, inname) + FILE *in; + char *inname; + { + register char *hdr; + int ishdr = YES; + long nolimit = -1; + static int washdr = YES; + + if (!washdr) + return; + while ((hdr = gethdr(in, &nolimit, &ishdr)) != NULL && ishdr) { + register char *cp; + static char canonmsgid[] = "Message-Id:"; + static char magicmsgid[] = "Message-ID:"; + + /* capitalise initial letter of each word, Message-ID: special */ + for (cp = hdr; *cp != ':' && *cp != '\0'; cp++) + if (cp == hdr || cp[-1] == '-') { + if (isascii(*cp) && islower(*cp)) + *cp = toupper(*cp); + } else + if (isascii(*cp) && isupper(*cp)) + *cp = tolower(*cp); + if (STREQN(hdr, canonmsgid, sizeof canonmsgid - 1)) + (void) strncpy(hdr, magicmsgid, sizeof magicmsgid - 1); + (void) fputs(hdr, stdout); + /* must not free hdr; gethdr will do so automatically */ + } + if (hdr != NULL) + free(hdr); + if (!ishdr) + washdr = NO; + } end of patch 14-Sep-1989 -- V7 /bin/mail source: 554 lines.| Henry Spencer at U of Toronto Zoology 1989 X.400 specs: 2200+ pages. | uunet!attcan!utzoo!henry henry@zoo.toronto.edu