DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T U

⟦3b692f12b⟧ TextFile

    Length: 58859 (0xe5eb)
    Types: TextFile
    Notes: Uncompressed file

Derivation

└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
    └─⟦ba1215703⟧ »EurOpenD3/news/cnews/10-Jan-1990.Z« 
        └─⟦this⟧ 

TextFile

To: utai!uunet!source-patches
Subject: C News patch of 10-Jan-1990

This one introduces one major change:  relaynews now completely implements
the silly "Supersedes" header.  We still think that most current uses of
Supersedes do not justify it, but Brad Templeton (always the nuisance :-))
has found a real use for it, and there may be more.  Actually, to head off
yet more silly new headers, we implement an "Also-Control" header that
lets any control-message function be piggybacked on a normal article, and
do "Supersedes" by s/Supersedes:/Also-Control: cancel/.

We've trying to clear our fairly lengthy low-priority-to-be-looked-at
lists, some of it long overdue.  A spacefor variant for Xenix and Microport
Unixes.  Revision of expire and mkdbm to invoke dbmclose(), in preparation
for dbz, and a fake dbmclose() for systems that have dbm but not dbmclose().
Expire's reporting of bad expiry dates is now optional, invoked by -g.
Everything has been checked over to be sure that files under $NEWSARTS
with dots in their names are always ignored, so people who want to annotate
the tree can do so.  Memory leak in histinfo fixed.  Upact and updatemin
use a more sensible name for their temporary file, and are a bit more
paranoid about it.  Spurious system noises in error messages removed.
More fixes for rsh misbehavior.  expire -t output format documented.
Reporting of articles arriving in newsgroups you don't subscribe to.
Beginnings of a new document, notebook/problems, discussing common porting
problems.  And the usual bunch of minor cleanups.

start of patch 10-Jan-1990
(suggested archive name: `pch10Jan90.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
Prereq: 14-Sep-1989
Prereq: 13-Nov-1989
*** PATCHDATES.old	Wed Jan 10 17:56:27 1990
--- PATCHDATES	Wed Jan 10 17:56:27 1990
***************
*** 1,7 ****
--- 1,8 ----
  23-Jun-1989
  7-Jul-1989
  23-Jul-1989
  22-Aug-1989
  24-Aug-1989
  14-Sep-1989
  13-Nov-1989
+ 10-Jan-1990

Changed files, if any:

*** cnpatch/old/COPYRIGHT	Tue Jun 20 18:55:22 1989
--- COPYRIGHT	Sat Dec 30 23:11:40 1989
***************
*** 1,4 ****
  /*
!  * Copyright (c) University of Toronto 1985, 1986, 1987, 1988, 1989.
   * All rights reserved.
   * Written mostly by Geoffrey Collyer and Henry Spencer.
--- 1,4 ----
  /*
!  * Copyright (c) University of Toronto 1985, 1986, 1987, 1988, 1989, 1990.
   * All rights reserved.
   * Written mostly by Geoffrey Collyer and Henry Spencer.

*** cnpatch/old/ROADMAP	Tue Jun 20 18:55:27 1989
--- ROADMAP	Sat Dec 30 23:11:26 1989
***************
*** 6,10 ****
  	an official part of C News.
  doc	User documentation, including "install" which discusses how to
! 	install C News.
  expire	Expire and friends, including history rebuilding and active-file
  	updating (neither of which is done by expire in C News).  Ought
--- 6,14 ----
  	an official part of C News.
  doc	User documentation, including "install" which discusses how to
! 	install C News.  Although the documentation is supplied as troff
! 	sources, no complex formatting is used and it should be quite
! 	readable even if you don't have a troff to format it.  We supply
! 	preformatted output for doc/install, as doc/install.out, just
! 	as a precaution.
  expire	Expire and friends, including history rebuilding and active-file
  	updating (neither of which is done by expire in C News).  Ought

*** cnpatch/old/batch/Makefile	Mon Nov 13 17:39:42 1989
--- batch/Makefile	Sat Dec 30 02:13:07 1989
***************
*** 44,47 ****
--- 44,50 ----
  	for f in $(PGMS) ; do cmp $(PGMDIR)/$$f $$f ; done
  
+ check:	$(PGMS)
+ 	for f in $(PGMS) ; do cmp $(PGMDIR)/$$f $$f || true ; done
+ 
  newsinstall:	batchparms
  	-if test ! -d $(OUTGOING) ; then mkdir $(OUTGOING) ; fi

*** cnpatch/old/conf/Makefile	Thu Aug 24 16:39:47 1989
--- conf/Makefile	Sun Dec 31 01:07:31 1989
***************
*** 16,19 ****
--- 16,20 ----
  DIRS = batch conf expire h hfake input $(LIBDIRS) misc relay rna
  CMPDIRS = batch conf expire input man misc relay rna
+ RDIRS = batch expire input relay
  SHS = doit.root doit.bin doit.news again.root
  
***************
*** 46,51 ****
  	./subst -f substitutions `sed 's;^;../;' subst.hs subst.gc`
  
- spacefors:	spacefor.sysv spacefor.v7 spacefor.sgi spacefor.bsd spacefor.ultrix spacefor.null
- 
  spacefor.bsd:	spacefor.proto Makefile
  	cp spacefor.proto $@
--- 47,50 ----
***************
*** 57,60 ****
--- 56,62 ----
  	sed '/dfunit=/s/1024/512/;/awk/s~|~| sed "s/.*:/: :/" |~;/nf = 4/s//nf = 3/;/stupid/s/4BSD/System V/' spacefor.proto >$@
  
+ spacefor.xenix:	spacefor.proto Makefile
+ 	sed '/dfunit=/s/1024/512/;/awk/s~|~| sed "s/.*:/: :/" |~;/nr = 2/s//nr = 1/;/nf = 4/s//nf = 3/;/stupid/s/4BSD/Xenix/' spacefor.proto >$@
+ 
  spacefor.sgi:	spacefor.proto Makefile
  	sed '/dfunit=/s/1024/512/;/nf = 4/s//nf = 5/;/stupid/s/4BSD/SGI/' spacefor.proto >$@
***************
*** 86,90 ****
  clean:
  	rm -f spacefor.sysv spacefor.v7 spacefor.null queuelen.null
! 	rm -f spacefor.sgi
  	rm -f config mailname organization server whoami hostname errlog
  	rm -f substitutions history history.pag history.dir active localgroups
--- 88,92 ----
  clean:
  	rm -f spacefor.sysv spacefor.v7 spacefor.null queuelen.null
! 	rm -f spacefor.sgi spacefor.xenix
  	rm -f config mailname organization server whoami hostname errlog
  	rm -f substitutions history history.pag history.dir active localgroups
***************
*** 108,111 ****
--- 110,116 ----
  cmps:
  	for d in $(CMPDIRS) ; do cd ../$$d ; make cmp RBIN=/usr/lib/uucp/bin ; done
+ 
+ rs:
+ 	for d in $(RDIRS) ; do cd ../$$d ; make r ; done
  
  save:	$(SHS)

*** cnpatch/old/conf/build	Mon Nov 13 17:39:43 1989
--- conf/build	Mon Jan  1 00:25:38 1990
***************
*** 377,382 ****
  		esac
  		dbm="DBM=$answer"
  		;;
! *)	fake="$fake dbm.o"
  	dbm='DBM='
  	echo "Okay, we'll fake it for you.  You might want to look at"
--- 377,387 ----
  		esac
  		dbm="DBM=$answer"
+ 		./query 'Does your dbm have a dbmclose() function [no]? '
+ 		read answer
+ 		case "$answer" in
+ 		n*|N*|'')	fake="$fake dbmclose.o"	;;
+ 		esac
  		;;
! *)	fake="$fake dbm.o dbmclose.o"
  	dbm='DBM='
  	echo "Okay, we'll fake it for you.  You might want to look at"
***************
*** 392,398 ****
  echo 'are faster than those in any stdio we know; they are compatible with'
  echo 'most AT&T-derived stdios.  If they work on your system, they are a'
! echo 'major performance win for C News.  There is a simple compatibility'
! echo 'check run after the library is built.  The only system we know of'
! echo 'where the test works but the functions do not is SunOS 4.0.'
  ./query 'Do you want to use our fast stdio library [yes]? '
  read libstdio
--- 397,403 ----
  echo 'are faster than those in any stdio we know; they are compatible with'
  echo 'most AT&T-derived stdios.  If they work on your system, they are a'
! echo 'major performance win for C News.  There is a fairly thorough'
! echo 'compatibility check run after the library is built; as far as we'
! echo 'know, if the test works, the functions do (even on SunOS 4.0).'
  ./query 'Do you want to use our fast stdio library [yes]? '
  read libstdio
***************
*** 602,605 ****
--- 607,611 ----
  echo '	sgi	Silicon Graphics Iris systems'
  echo '	ultrix	DEC Ultrix 3.0 (and later) (and earlier??)'
+ echo '	xenix	some (all?) Xenixes, notably SCO'
  echo '	v7	plain old style:  no headers or fluff, just name and number'
  echo "	null	don't know or don't care how much space is available"
***************
*** 610,614 ****
  	case "$dftype" in
  	'')	dftype=bsd	;;
! 	sysv)	echo 'Beware -- test "spacefor" to make sure it works.'
  		echo 'System V "df" formats vary widely, indeed wildly.'
  		echo '"Consider it standard".  Sure.'
--- 616,621 ----
  	case "$dftype" in
  	'')	dftype=bsd	;;
! 	sysv|xenix)
! 		echo 'Beware -- test "spacefor" to make sure it works.'
  		echo 'System V "df" formats vary widely, indeed wildly.'
  		echo '"Consider it standard".  Sure.'
***************
*** 616,620 ****
  	esac
  	case "$dftype" in
! 	bsd|sysv|sgi|ultrix|v7|null)	break	;;
  	esac
  	echo 'Sorry, no such choice is available.'
--- 623,627 ----
  	esac
  	case "$dftype" in
! 	bsd|sysv|sgi|ultrix|xenix|v7|null)	break	;;
  	esac
  	echo 'Sorry, no such choice is available.'

*** cnpatch/old/conf/spacefor.proto	Thu Sep 14 16:03:27 1989
--- conf/spacefor.proto	Thu Nov 16 17:07:30 1989
***************
*** 22,26 ****
  	if test " $server" != " $me"
  	then
! 		exec rsh $server /bin/sh -c "'PATH=$PATH `basename $0` $*'"
  		# does not return
  	fi
--- 22,26 ----
  	if test " $server" != " $me"
  	then
! 		exec rsh $server -n /bin/sh -c "'PATH=$PATH `basename $0` $*'"
  		# does not return
  	fi
***************
*** 33,37 ****
  
  # argument to df, df units, and free space desired (in df units)
! dfunit=1024			# default unit (bytes)
  case "$2" in
  incoming)	arg="$NEWSARTS/in.coming" ; desire=5000 ;;
--- 33,37 ----
  
  # argument to df, df units, and free space desired (in df units)
! dfunit=1024			# default df unit (bytes)
  case "$2" in
  incoming)	arg="$NEWSARTS/in.coming" ; desire=5000 ;;
***************
*** 43,46 ****
--- 43,53 ----
  		exit 2 ;;
  esac
+ 
+ # In the following, the initialization of nf determines which field the
+ # block count comes from, and the one for nr determines which line.  For
+ # System V, the Makefile edits in a sed which tries to strip silliness
+ # off in a reasonably System-V-variant-indepedent way.  Expr would be
+ # faster than awk, but on a 16-bit machine, expr does 16-bit arithmetic,
+ # which isn't enough.
  
  # this is set up for the stupid 4BSD df

*** cnpatch/old/conf/sys.proto	Thu Sep 14 16:03:28 1989
--- conf/sys.proto	Wed Jan  3 15:11:50 1990
***************
*** 1,6 ****
  # line indicating what we are willing to receive; note local groups on end
  ME:comp,news,sci,rec,misc,soc,talk,to,can,ont,tor,ut
  
! # sample insignificant feed not using batching
  huey:news.config,to.huey/all::uux - -r -gd huey!rnews
  
--- 1,10 ----
+ # Only the ME line is mandatory; the others are just samples of how to do
+ # things.  Virtually everything will need modifying for your local feeds
+ # and newsgroups.
+ 
  # line indicating what we are willing to receive; note local groups on end
  ME:comp,news,sci,rec,misc,soc,talk,to,can,ont,tor,ut
  
! # sample insignificant feed not using batching (for special situations only)
  huey:news.config,to.huey/all::uux - -r -gd huey!rnews
  
***************
*** 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)
--- 24,28 ----
  # Send ihave telling louie what we have -- batcher turns the batch into a
  # giant control message and posts it to "to.louie".  (#1)
! louie:comp,news,sci,rec,misc,soc,talk,!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)
***************
*** 29,32 ****
  louie-real:to.louie/sendme:f:louie/togo
  # Actually the last two could be combined.
! # and send local postings to louie without waiting (beware ihave/sendme)
  louie-local:comp,news,sci,rec,misc,soc,talk/all,!sendme,!ihave:L:
--- 33,38 ----
  louie-real:to.louie/sendme:f:louie/togo
  # Actually the last two could be combined.
! 
! # also, since ihave/sendme is slow, send local postings to louie without
! # waiting (beware ihave/sendme)
  louie-local:comp,news,sci,rec,misc,soc,talk/all,!sendme,!ihave:L:

*** cnpatch/old/doc/interface	Tue Aug 22 14:47:44 1989
--- doc/interface	Wed Jan  3 14:06:13 1990
***************
*** 1,3 ****
! .DA "19 Aug 1989"
  .TL
  The Interface Between C News And The Outside World
--- 1,3 ----
! .DA "3 Jan 1990"
  .TL
  The Interface Between C News And The Outside World
***************
*** 332,349 ****
  such an update.
  It should be run as \fInews\fR.
! .PP
! \fIRelay/relaynews\fR
! does not implement the ``Supersedes:'' header, which we loathe
! as a crude solution to the wrong problem.
! Alas, the network-map distribution in
! \fIcomp.mail.maps\fR relies heavily on it.
! Our preferred approach is to process map articles as they arrive and
! then expire them normally (using \fIexpire\fR's expiry-date-override
! features to insist that they expire promptly).
! However, for those who don't do this, and don't want to have megabytes
! of obsolete map data piling up,
! \fIexpire/superkludge\fR will remove superseded files in specified
! newsgroups.
! It should be run as \fInews\fR by \fIcron\fR, perhaps nightly.
  .SH
  Reboots and Administration
--- 332,337 ----
  such an update.
  It should be run as \fInews\fR.
! A much faster, but somewhat less portable, C implementation is
! supplied as \fIexpire/updatemin\fR.
  .SH
  Reboots and Administration

*** cnpatch/old/expire/Makefile	Thu Sep 14 16:03:29 1989
--- expire/Makefile	Wed Jan  3 14:03:47 1990
***************
*** 7,11 ****
  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 \
--- 7,11 ----
  LIBS= ../libcnews.a
  THEM = expire histdups histinfo histslash mkdbm mkhistory \
! 	upact doexpire mkadir recovact
  DTR = README Makefile dircheck doexpire expire.c histdups histinfo.c \
  	histslash.c mkdbm.c mkhistory pgood superkludge tgood upact \
***************
*** 31,34 ****
--- 31,37 ----
  	for f in $(THEM) ; do cmp $(NEWSBIN)/expire/$$f $$f ; done
  
+ check:	$(THEM)
+ 	for f in $(THEM) ; do cmp $(NEWSBIN)/expire/$$f $$f || true ; done
+ 
  newsinstall:	explist.proto
  	-if test ! -r $(NEWSCTL)/explist ; then cp explist.proto $(NEWSCTL)/explist ; fi
***************
*** 187,191 ****
  
  # the regression test proper
! r:	$(THEM) $(UPACT) dircheck setup tgood pgood
  	chmod +x dircheck $(THEM)
  	$(RUN) -c explist
--- 190,194 ----
  
  # the regression test proper
! r:	$(THEM) $(UPACT) dircheck setup tgood pgood superkludge
  	chmod +x dircheck $(THEM)
  	$(RUN) -c explist

*** cnpatch/old/expire/README	Tue Aug 22 14:47:45 1989
--- expire/README	Wed Jan  3 14:02:58 1990
***************
*** 30,31 ****
--- 30,33 ----
  pgood and tgood are regression-test output-should-look-like-this files.
  mkadir is what expire invokes to create archiving subdirectories.
+ superkludge is an old implementation of the Supersedes header, now
+ 	superseded :-) by the full implementation in relaynews.

*** cnpatch/old/expire/expire.c	Mon Nov 13 17:39:44 1989
--- expire/expire.c	Sun Dec 31 01:39:56 1989
***************
*** 78,81 ****
--- 78,82 ----
  int rebuild = 1;		/* rebuild history files */
  int violate = 0;		/* non-rfc822 case-sensitive messageIDs */
+ int getdgrump = 0;		/* report un-getdate()able expiry dates */
  
  long nkept = 0;			/* count of articles not expired */
***************
*** 168,172 ****
  	ftime(&ftnow);
  
! 	while ((c = getopt(argc, argv, "pa:sF:cn:tlvrVd")) != EOF)
  		switch (c) {
  		case 'p':	/* print info line for archived articles */
--- 169,173 ----
  	ftime(&ftnow);
  
! 	while ((c = getopt(argc, argv, "pa:sF:cn:tlvrVgd")) != EOF)
  		switch (c) {
  		case 'p':	/* print info line for archived articles */
***************
*** 203,206 ****
--- 204,210 ----
  			violate = 1;
  			break;
+ 		case 'g':	/* report getdate() failures on expiry dates */
+ 			getdgrump = 1;
+ 			break;
  		case 'd':	/* debug */
  			expdebug = 1;
***************
*** 491,496 ****
  
  	(void) close(old);
! 	if (rebuild)
  		eufclose(new, "history.n");
  
  	if (testing)
--- 495,502 ----
  
  	(void) close(old);
! 	if (rebuild) {
  		eufclose(new, "history.n");
+ 		dbmclose();
+ 	}
  
  	if (testing)
***************
*** 565,569 ****
  	else {
  		expdate = readdate(subfield[1]);
! 		if (expdate == NODATE) {
  			errno = 0;
  			warning("bad expiry date in `%.40s...',", line);
--- 571,575 ----
  	else {
  		expdate = readdate(subfield[1]);
! 		if (expdate == NODATE && getdgrump) {
  			errno = 0;
  			warning("bad expiry date in `%.40s...',", line);

*** cnpatch/old/expire/histinfo.c	Thu Sep 14 16:03:31 1989
--- expire/histinfo.c	Sat Dec 30 01:52:05 1989
***************
*** 6,9 ****
--- 6,10 ----
  #include <sys/types.h>
  #include <sys/stat.h>		/* for modified time (date received) */
+ #include <string.h>
  #include "config.h"
  #include "fgetmfs.h"
***************
*** 55,61 ****
  	while ((inname = fgetms(stdin)) != NULL) {
  		inname[strlen(inname)-1] = '\0';	/* kill newline */
! 		in = efopen(inname, "r");
! 		process(in, inname);
! 		(void) fclose(in);
  		free(inname);
  	}
--- 56,64 ----
  	while ((inname = fgetms(stdin)) != NULL) {
  		inname[strlen(inname)-1] = '\0';	/* kill newline */
! 		if (strchr(inname, '.') == NULL) {	/* skip dot names */
! 			in = efopen(inname, "r");
! 			process(in, inname);
! 			(void) fclose(in);
! 		}
  		free(inname);
  	}
***************
*** 79,83 ****
  	static char expnm[] =    "Expires: ";
  	register char *p;
- 	extern char *strchr();
  
  	expiry = strsave("-");
--- 82,85 ----
***************
*** 97,100 ****
--- 99,104 ----
  		free(line);
  	}
+ 	if (line != NULL)
+ 		free(line);
  
  	/* generate the file name */

*** cnpatch/old/expire/mkdbm.c	Thu Sep 14 16:03:31 1989
--- expire/mkdbm.c	Tue Nov 28 19:24:46 1989
***************
*** 1,10 ****
  /*
   * mkdbm - rebuild dbm file for a history file
-  *
-  * History file on standard input; the dbm database is generated as
-  * hist.dir and hist.pag.
   */
  #include <stdio.h>
  #include <string.h>
  #include "fgetmfs.h"
  #include "case.h"
--- 1,8 ----
  /*
   * mkdbm - rebuild dbm file for a history file
   */
  #include <stdio.h>
  #include <string.h>
+ #include "alloc.h"
  #include "fgetmfs.h"
  #include "case.h"
***************
*** 14,18 ****
  typedef struct { char *dptr; int dsize; } datum;
  
! main()
  {
  	register char *scan;
--- 12,18 ----
  typedef struct { char *dptr; int dsize; } datum;
  
! main(argc, argv)
! int argc;
! char *argv[];
  {
  	register char *scan;
***************
*** 21,33 ****
  	datum rhs;
  	register char *line;
  
! 	(void) close(creat("hist.dir", 0666));
! 	(void) close(creat("hist.pag", 0666));
! 	if (dbminit("hist") < 0)
! 		error("unable to do dbminit(\"hist\")", "");
  
  	for (;;) {
! 		place = ftell(stdin);
! 		line = fgetms(stdin);
  		if (line == NULL)
  			break;
--- 21,40 ----
  	datum rhs;
  	register char *line;
+ 	FILE *f;
+ 	extern FILE *efopen();
  
! 	if (argc < 2) {
! 		fprintf(stderr, "Usage: mkdbm historyfile\n");
! 		exit(2);
! 	}
! 	f = efopen(argv[1], "r");
! 	(void) close(creat(str3save(argv[1], ".", "dir"), 0666));
! 	(void) close(creat(str3save(argv[1], ".", "pag"), 0666));
! 	if (dbminit(argv[1]) < 0)
! 		error("unable to do dbminit(`%s')", argv[1]);
  
  	for (;;) {
! 		place = ftell(f);
! 		line = fgetms(f);
  		if (line == NULL)
  			break;
***************
*** 49,52 ****
--- 56,71 ----
  		free(line);
  	}
+ 
+ 	dbmclose();
  	exit(0);
+ }
+ 
+ /*
+  - unprivileged - needed due to library interdependencies
+  */
+ /* ARGSUSED */
+ void
+ unprivileged(reason)
+ char *reason;
+ {
  }

*** cnpatch/old/expire/mkhistory	Thu Sep 14 16:03:32 1989
--- expire/mkhistory	Sun Nov 26 01:32:54 1989
***************
*** 32,36 ****
  	echo "$0:     (grep history file for '@trash' to see them)" >&2
  fi
! mkdbm <history.n
  mv history history.o &&		# install new ASCII history file
  mv history.n history &&
--- 32,36 ----
  	echo "$0:     (grep history file for '@trash' to see them)" >&2
  fi
! mkdbm history.n
  mv history history.o &&		# install new ASCII history file
  mv history.n history &&
***************
*** 37,39 ****
  rm -f history.pag &&		# and related dbm files
  rm -f history.dir &&
! mv hist.pag history.pag && mv hist.dir history.dir
--- 37,39 ----
  rm -f history.pag &&		# and related dbm files
  rm -f history.dir &&
! mv history.n.pag history.pag && mv history.n.dir history.dir

*** cnpatch/old/expire/upact	Tue Aug 22 14:47:46 1989
--- expire/upact	Wed Dec 20 16:03:32 1989
***************
*** 18,21 ****
--- 18,28 ----
  esac
  
+ rm -f active.tmp
+ if test -f active.tmp
+ then
+ 	echo "$0: active.tmp exists and can't be removed; aborting" >&2
+ 	exit 1
+ fi
+ 
  # lock news system
  lock="$NEWSCTL/LOCK"
***************
*** 50,54 ****
  
  	echo $group $max $min $fourth
! done <active >active.new
  
  # replace active, carefully
--- 57,61 ----
  
  	echo $group $max $min $fourth
! done <active >active.tmp
  
  # replace active, carefully
***************
*** 55,59 ****
  rm -f active.old
  ln active active.old
! mv active.new active
  
  exit 0
--- 62,66 ----
  rm -f active.old
  ln active active.old
! mv active.tmp active
  
  exit 0

*** cnpatch/old/expire/updatemin.c	Thu Sep 14 16:03:33 1989
--- expire/updatemin.c	Wed Dec 20 16:04:50 1989
***************
*** 24,28 ****
  long lowest();
  
! char newname[] = "active.new";
  
  char *progname;
--- 24,28 ----
  long lowest();
  
! char newname[] = "active.tmp";
  
  char *progname;

*** cnpatch/old/hfake/Makefile	Tue Jun 20 18:58:03 1989
--- hfake/Makefile	Wed Jan 10 17:12:27 1990
***************
*** 2,6 ****
  
  # beware -- build knows about NEEDED
! NEEDED =  ../include/stdlib.h
  
  all:	$(NEEDED)
--- 2,6 ----
  
  # beware -- build knows about NEEDED
! NEEDED =  ../include/stdlib.h ../include/string.h
  
  all:	$(NEEDED)

*** cnpatch/old/input/Makefile	Thu Aug 24 16:39:52 1989
--- input/Makefile	Sat Dec 30 02:14:57 1989
***************
*** 41,44 ****
--- 41,50 ----
  	ls -lg $(NEWSBIN)/input/newsspool | egrep -s '^-rwsrwsr-x  1 news     news'
  
+ check:	$(THEM)
+ 	for f in $(THEM) ; do cmp $(NEWSBIN)/input/$$f $$f || true ; done
+ 	cmp rnews $(RBIN)/rnews || true
+ 	cmp rnews $(RBIN)/cunbatch || true
+ 	ls -lg $(NEWSBIN)/input/newsspool | egrep -s '^-rwsrwsr-x  1 news     news'
+ 
  newsinstall:
  	: nothing

*** cnpatch/old/input/newsrun	Tue Aug 22 14:47:46 1989
--- input/newsrun	Wed Nov 15 15:14:08 1989
***************
*** 116,120 ****
  		else
  			# N.B.: rsh always returns exit status 0!
! 			rsh $server "PATH=$PATH relaynews -r -n" <$text
  		fi
  		st=$?
--- 116,120 ----
  		else
  			# N.B.: rsh always returns exit status 0!
! 			rsh $server /bin/sh -c "PATH=$PATH relaynews -r -n" <$text
  		fi
  		st=$?

*** cnpatch/old/libc/warning.c	Tue Jun 20 18:58:41 1989
--- libc/warning.c	Sat Dec 30 01:46:05 1989
***************
*** 11,14 ****
--- 11,15 ----
  {
  	char *cmdname;
+ 	int saverrno;
  	extern int errno, sys_nerr;
  	extern char *sys_errlist[];
***************
*** 16,19 ****
--- 17,21 ----
  	extern char *getenv();
  
+ 	saverrno = errno;		/* so isatty(3) won't clobber it */
  	(void) fflush(stdout);				/* hack */
  	cmdname = getenv("CMDNAME");
***************
*** 23,28 ****
  		fprintf(stderr, "%s: ", progname);
  	fprintf(stderr, s1, s2);
! 	if (errno > 0 && errno < sys_nerr)
! 		fprintf(stderr, " (%s)", sys_errlist[errno]);
  	fprintf(stderr, "\n");
  	errno = 0;
--- 25,30 ----
  		fprintf(stderr, "%s: ", progname);
  	fprintf(stderr, s1, s2);
! 	if (saverrno > 0 && saverrno < sys_nerr)
! 		fprintf(stderr, " (%s)", sys_errlist[saverrno]);
  	fprintf(stderr, "\n");
  	errno = 0;

*** cnpatch/old/libfake/Makefile	Thu Aug 24 16:39:55 1989
--- libfake/Makefile	Wed Jan 10 17:15:59 1990
***************
*** 7,11 ****
  ALL = dbm.o fsync.o getopt.o ldiv.o memchr.o memcmp.o memcpy.o \
  memset.o mkdir.o putenv.o strchr.o strcspn.o strpbrk.o strrchr.o \
! strspn.o strtok.o symlink.o
  
  # beware -- build knows about NEEDED
--- 7,11 ----
  ALL = dbm.o fsync.o getopt.o ldiv.o memchr.o memcmp.o memcpy.o \
  memset.o mkdir.o putenv.o strchr.o strcspn.o strpbrk.o strrchr.o \
! strspn.o strtok.o symlink.o dbmclose.o
  
  # beware -- build knows about NEEDED

*** cnpatch/old/man/expire.8	Thu Sep 14 16:03:40 1989
--- man/expire.8	Wed Jan  3 14:01:37 1990
***************
*** 7,11 ****
  .\" =()<.ds m @<NEWSMASTER>@>()=
  .ds m usenet
! .TH EXPIRE 8 "13 Sept 1989" "C News"
  .SH NAME
  expire, doexpire \- expire old news
--- 7,11 ----
  .\" =()<.ds m @<NEWSMASTER>@>()=
  .ds m usenet
! .TH EXPIRE 8 "3 Jan 1990" "C News"
  .SH NAME
  expire, doexpire \- expire old news
***************
*** 16,21 ****
  .br
  recovact \- partially recover news active file
- .br
- superkludge \- implement stupid Supersedes header in news
  .SH SYNOPSIS
  .B \*b/expire/expire
--- 16,19 ----
***************
*** 45,48 ****
--- 43,48 ----
  ] [
  .B \-r
+ ] [
+ .B \-g
  ]
  [ controlfile ]
***************
*** 56,65 ****
  .br
  .B \*b/expire/recovact
- .br
- .B \*b/expire/superkludge
- [
- .B \-v
- ]
- newsgroup ...
  .SH DESCRIPTION
  .I Expire
--- 56,59 ----
***************
*** 182,185 ****
--- 176,188 ----
  print (on standard error) a shell-script-like description of what would
  be done, but don't do it.
+ In the absence of archiving, all output lines will be of the form
+ ``\fBremove\fR\ \fIname\fR'', where \fIname\fR is a pathname relative
+ to \fI\*a\fR.
+ If an article is to be archived, this will be preceded (on the same
+ line) by ``\fBcopy\fR\ \fIname\fR\ \fIdir\fR\ \fB;\fR\ '', where \fIname\fR
+ is as in \fBremove\fR and \fIdir\fR is an archiving directory
+ (including any `=' prefix)
+ as specified by the control file
+ or the \fB\-a\fR option.
  .TP
  .BR \-l
***************
*** 199,202 ****
--- 202,211 ----
  report some statistics after termination.
  .TP
+ .BR \-g
+ report expiry dates that \fIgetdate\fR(3) does not like.
+ .I Expire
+ ignores such dates, treating the article as if it had no explicit
+ expiry date.
+ .TP
  .BR \-d
  turn on (voluminous and cryptic) debugging output.
***************
*** 236,247 ****
  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
- .I Superkludge
- inspects the files in \fI\*a\fR for the \fInewsgroup\fR(s)
- given, and removes any that have been superseded, according to the
- `Supersedes' header, by newer ones.
- The \fIhistory\fR file is not altered; it's not worth the trouble.
- The \fB\-v\fR option produces a report of how many articles have been
- superseded in each \fInewsgroup\fR.
  .SH FILES
  .ta 6c
--- 245,248 ----
***************
*** 270,282 ****
  although such lines are rare.
  .PP
! \fIUpact\fR and \fIsuperkludge\fR are distasteful kludges,
! but then, so are the third field of the \fIactive\fR file and the
! `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
  with the `=' feature, since the article numbers will collide with each
  other and expire doesn't do anything about this.
--- 271,284 ----
  although such lines are rare.
  .PP
! \fIUpact\fR is a distasteful kludge,
! but then, so is the third field of the \fIactive\fR file.
  .PP
  One cannot put more than one newsgroup into a single archiving directory
  with the `=' feature, since the article numbers will collide with each
  other and expire doesn't do anything about this.
+ .PP
+ .I Mkhistory
+ is inherently incapable of reconstructing history-file lines corresponding
+ to expired articles.
+ Protection against old articles reappearing is thus somewhat limited for
+ a while after the history file is rebuilt.

*** cnpatch/old/man/newsaux.8	Mon Nov 13 17:39:47 1989
--- man/newsaux.8	Sun Dec 31 01:34:07 1989
***************
*** 7,11 ****
  .\" =()<.ds m @<NEWSMASTER>@>()=
  .ds m usenet
! .TH NEWSAUX 8 "15 Sept 1989" "C News"
  .SH NAME
  spacefor \- check available space for news
--- 7,11 ----
  .\" =()<.ds m @<NEWSMASTER>@>()=
  .ds m usenet
! .TH NEWSAUX 8 "30 Dec 1989" "C News"
  .SH NAME
  spacefor \- check available space for news
***************
*** 263,264 ****
--- 263,268 ----
  \fIDelgroup\fR does not remove files or directories from \*a, although it
  prints a reminder to do so.
+ .PP
+ Various nuisances can result if the maintenance utilities are run as
+ \fIroot\fR rather than as the owner of the news database.
+ It's difficult to defend against this.

*** cnpatch/old/man/relaynews.8	Fri Jul  7 15:40:08 1989
--- man/relaynews.8	Wed Jan  3 14:07:31 1990
***************
*** 7,11 ****
  .\" =()<.ds m @<NEWSMASTER>@>()=
  .ds m usenet
! .TH RELAYNEWS 8 "4 July 1989" "C News"
  .SH NAME
  relaynews \- store and forward netnews articles
--- 7,11 ----
  .\" =()<.ds m @<NEWSMASTER>@>()=
  .ds m usenet
! .TH RELAYNEWS 8 "2 January 1990" "C News"
  .SH NAME
  relaynews \- store and forward netnews articles
***************
*** 98,101 ****
--- 98,120 ----
  is not a real newsgroup.
  .PP
+ An article which contains an
+ .B Also-Control:
+ header is treated normally
+ except that the contents of the header
+ are executed as if they were the contents of a
+ .B Control:
+ header.
+ Such an article is a form of
+ .I "hybrid message"
+ since it functions as an ordinary article
+ yet also causes control functions to be executed.
+ The
+ .B Supersedes:
+ header is a special case
+ and is rewritten internally
+ .I only
+ to
+ .BR "Also-Control: cancel" .
+ .PP
  Articles which contain no locally-known
  (to the
***************
*** 222,228 ****
  (e.g. something like Eunice but on a PDP-11)
  will be filed incorrectly:
! any symbolic links under \*a will point at a non-existent
! filename.
! .br
  A control message which cannot be filed in the
  .B control
--- 241,248 ----
  (e.g. something like Eunice but on a PDP-11)
  will be filed incorrectly:
! any symbolic links under
! .B \*a
! will point at a non-existent filename.
! .PP
  A control message which cannot be filed in the
  .B control
***************
*** 241,245 ****
  .B control
  pseudo-group.
! .br
  .I Relaynews
  could run faster in some circumstances
--- 261,265 ----
  .B control
  pseudo-group.
! .PP
  .I Relaynews
  could run faster in some circumstances
***************
*** 246,253 ****
  and would be simpler
  if
! .I Control:
  were required to be the first header,
  if present,
  and if
! .I Newsgroups:
  were required to be the next.
--- 266,285 ----
  and would be simpler
  if
! .B Control:
  were required to be the first header,
  if present,
  and if
! .B Newsgroups:
  were required to be the next.
+ .PP
+ The whole control message and hybrid message situation
+ is a festering bug.
+ Either control messages should be eliminated,
+ or all forms of backward compatibility should be dropped
+ (including
+ .B Control:
+ and
+ .BR Supersedes: )
+ and only
+ .B Also-Control:
+ should be supported.

*** cnpatch/old/misc/Makefile	Thu Sep 14 16:03:43 1989
--- misc/Makefile	Sat Dec 30 02:17:11 1989
***************
*** 31,34 ****
--- 31,38 ----
  	for f in $(UTILS) ; do cmp $(NEWSBIN)/$$f $$f ; done
  
+ check:	$(THEM)
+ 	for f in $(MAINT) ; do cmp $(NEWSBIN)/maint/$$f $$f || true ; done
+ 	for f in $(UTILS) ; do cmp $(NEWSBIN)/$$f $$f || true ; done
+ 
  newsinstall:
  	: nothing
***************
*** 50,54 ****
  
  NHCFLAGS = -I$(RN) $(CFLAGS)
! RNEWSOBJS = $(RN)/history.o $(RN)/article.o $(RN)/hdrcommon.o \
   $(RN)/io.o $(RN)/msgs.o
  NHLIBS = $(LIBS) $(DBM)
--- 54,58 ----
  
  NHCFLAGS = -I$(RN) $(CFLAGS)
! RNEWSOBJS = $(RN)/history.o $(RN)/article.o $(RN)/hdrdefs.o \
   $(RN)/io.o $(RN)/msgs.o
  NHLIBS = $(LIBS) $(DBM)

*** cnpatch/old/misc/newsdaily	Mon Nov 13 17:39:49 1989
--- misc/newsdaily	Tue Dec 19 18:52:41 1989
***************
*** 116,119 ****
--- 116,129 ----
  	) >>$gripes
  fi
+ egrep '`' log.o | egrep 'no subscribed' | sed 's/.*`\(.*\)'"'"'.*/\1/' | sort |
+ 	uniq -c | sort -nr | sed 5q >$tmp
+ if test -s $tmp
+ then
+ 	(
+ 		echo 'leading five unsubscribed newsgroups:'
+ 		cat $tmp
+ 		echo
+ 	) >>$gripes
+ fi
  
  # and send it

*** cnpatch/old/misc/newshist.c	Tue Jun 20 19:00:05 1989
--- misc/newshist.c	Mon Nov 27 19:45:35 1989
***************
*** 11,15 ****
  static char *histfile;		/* unused */
  int remote;			/* to satisfy rnews code */
- int headdebug = 0;		/* no debugging */
  
  /*
--- 11,14 ----

*** cnpatch/old/notebook/bdiffs	Tue Jun 20 18:56:13 1989
--- notebook/bdiffs	Tue Jan  2 19:03:00 1990
***************
*** 39,43 ****
  .I rnews
  by linking to the name
! .I /usr/lib/news/LOCK
  and repeating until successful;
  there is no time-out
--- 39,43 ----
  .I rnews
  by linking to the name
! .B /usr/lib/news/LOCK
  and repeating until successful;
  there is no time-out
***************
*** 157,163 ****
  (e.g.
  .B usenet ).
! The superfluous
  .I Supersedes:
! header is not honoured.
  .PP
  .I "Newsgroup aliases."
--- 157,167 ----
  (e.g.
  .B usenet ).
! C news
! adds an
! .I Also-Control:
! header,
! of which
  .I Supersedes:
! is a special case.
  .PP
  .I "Newsgroup aliases."

*** cnpatch/old/notebook/ctlmsg	Tue Jun 20 18:56:24 1989
--- notebook/ctlmsg	Tue Jan  2 19:03:31 1990
***************
*** 62,66 ****
  .I relaynews
  by executing the command following
! .B Control: ,
  with a search path of
  .I $NEWSCTL/bin:$NEWSBIN/ctl
--- 62,66 ----
  .I relaynews
  by executing the command following
! .B Control:
  with a search path of
  .I $NEWSCTL/bin:$NEWSBIN/ctl
***************
*** 68,71 ****
--- 68,73 ----
  the control message article.
  The command inherits
+ the standard news search path
+ and
  .I relaynews 's
  user and group ids,

*** cnpatch/old/notebook/log	Sun Jul 23 00:48:12 1989
--- notebook/log	Sun Dec 31 01:30:54 1989
***************
*** 85,86 ****
--- 85,92 ----
  s	generated in response to a \fIsendme\fR control message	list of sites to which this article was relayed
  .TE
+ .PP
+ Beware that control-message handlers inherit
+ .I relaynew 's
+ standard output, so if any of them natters on standard output
+ (we believe none of ours does), the nattering will appear in
+ .B log .

*** cnpatch/old/notebook/rfcerrata	Mon Nov 13 17:39:49 1989
--- notebook/rfcerrata	Tue Jan  2 19:04:10 1990
***************
*** 77,81 ****
  B 2.11 interprets absence of the target article as ``unable to cancel''.
  It would improve the efficacy and reliability of
! .IR cancel s
  to propagate them anyway, given that feed anomalies are widespread.
  There have been verified instances in which cancellations did not achieve
--- 77,81 ----
  B 2.11 interprets absence of the target article as ``unable to cancel''.
  It would improve the efficacy and reliability of
! \fIcancel\fRs
  to propagate them anyway, given that feed anomalies are widespread.
  There have been verified instances in which cancellations did not achieve
***************
*** 84,88 ****
  C News interprets absence of the target article as deferred cancellation
  rather than failure to cancel, and propagates the
! .IR cancel .
  .SH
  ihave/sendme not documented
--- 84,88 ----
  C News interprets absence of the target article as deferred cancellation
  rather than failure to cancel, and propagates the
! \fIcancel\fR.
  .SH
  ihave/sendme not documented
***************
*** 105,109 ****
  .I remotesys .
  .SH
! case-sensitivity in message-ids
  .PP
  RFC 1036 says nothing about whether message-ids are case-sensitive or not,
--- 105,109 ----
  .I remotesys .
  .SH
! Case-sensitivity in message-ids
  .PP
  RFC 1036 says nothing about whether message-ids are case-sensitive or not,
***************
*** 118,119 ****
--- 118,129 ----
  matters appear to be extremely rare.)
  Simplification appears necessary.
+ .SH
+ New headers
+ .PP
+ The B news
+ .B Supersedes:
+ header needs to be documented in the next revision of the RFC,
+ as does the C news generalisation,
+ .B Also-Control:
+ (see
+ .I relaynews (8)).

*** cnpatch/old/relay/control.c	Thu Aug 24 16:39:59 1989
--- relay/control.c	Mon Nov 27 19:47:53 1989
***************
*** 22,26 ****
--- 22,28 ----
  #include "libc.h"
  #include "news.h"
+ #include "case.h"
  #include "config.h"
+ #include "control.h"
  #include "headers.h"
  #include "article.h"
***************
*** 30,33 ****
--- 32,39 ----
  #define NO_FILES ""
  #define SUBDIR binfile("ctl")		/* holds shell scripts */
+ #ifdef SLOWCTLMATCH
+ #define OLDCNTRL "all.all.ctl"
+ #endif
+ #define SFXOLDCNTRL ".ctl"
  
  /*
***************
*** 58,66 ****
  void
  ctlmsg(art)
! struct article *art;
  {
  	int pid, deadpid;
  	int wstatus;
- 	char *inname = art->a_tmpf, *ctlcmd = art->h.h_ctlcmd;
  	static char nmcancel[] = "cancel ";
  	static char nmihave[] = "ihave ";
--- 64,72 ----
  void
  ctlmsg(art)
! register struct article *art;
  {
+ 	register char *inname = art->a_tmpf, *ctlcmd = art->h.h_ctlcmd;
  	int pid, deadpid;
  	int wstatus;
  	static char nmcancel[] = "cancel ";
  	static char nmihave[] = "ihave ";
***************
*** 67,70 ****
--- 73,80 ----
  	static char nmsendme[] = "sendme ";
  
+ 	if (ctlcmd == NULL)
+ 		ctlcmd = art->h.h_etctlcmd;
+ 	if (ctlcmd == NULL)
+ 		return;
  	if (STREQN(ctlcmd, nmcancel, STRLEN(nmcancel))) {
  		art->a_status |= cancelart(ctlcmd + STRLEN(nmcancel));
***************
*** 102,106 ****
  STATIC boolean
  safecmd(cmd)			/* true if it's safe to system(3) cmd */
! char *cmd;
  {
  	register char *s;
--- 112,116 ----
  STATIC boolean
  safecmd(cmd)			/* true if it's safe to system(3) cmd */
! register char *cmd;
  {
  	register char *s;
***************
*** 245,247 ****
--- 255,300 ----
  	free(mailcmd);
  	_exit(1);
+ }
+ 
+ STATIC boolean
+ oldctl(hdrs)				/* true iff ngs match OLDCNTRL */
+ register struct headers *hdrs;
+ {
+ #ifdef SLOWCTLMATCH
+ 	return ngmatch(OLDCNTRL, hdrs->h_ngs);
+ #else
+ 	register int ngslen = strlen(hdrs->h_ngs);
+ 
+ 	if (ngslen < STRLEN(SFXOLDCNTRL))	/* ngs too short */
+ 		return NO;
+ 	else					/* check for .ctl suffix */
+ 		/*
+ 		 * This is more general than RFC 850 specifies, but this
+ 		 * generality seems harmless.  This doesn't work for e.g.
+ 		 * x.y.ctl,z.q, which is a darn shame, but that's a violation
+ 		 * of common sense.
+ 		 */
+ 		return STREQ(&hdrs->h_ngs[ngslen-STRLEN(SFXOLDCNTRL)],
+ 			SFXOLDCNTRL);
+ #endif						/* SLOWCTLMATCH */
+ }
+ 
+ hackoldctl(hdrs)			/* Handle the all.all.ctl hack. */
+ register struct headers *hdrs;
+ {
+ 	if (hdrs->h_ctlcmd == NULL && oldctl(hdrs))
+ 		hdrs->h_ctlcmd = strsave(hdrs->h_subj);
+ }
+ 
+ char *
+ hackhybrid(line)
+ register char *line;
+ {
+ 	static char stupersedes[] = "Supersedes:";
+ 	static char alsocan[] =     "Also-Control: cancel ";
+ 
+ 	if (CISTREQN(line, stupersedes, STRLEN(stupersedes)))
+ 		return str3save(alsocan, "", &line[STRLEN(stupersedes)]);
+ 	else
+ 		return strsave(line);
  }

*** cnpatch/old/relay/control.h	Tue Jun 20 19:01:03 1989
--- relay/control.h	Mon Nov 27 19:47:53 1989
***************
*** 1,2 ****
--- 1,5 ----
  /* imports from control.c */
  extern void ctlmsg();
+ extern char *hackhybrid();
+ 
+ #define CONTROL "control"		/* control message pseudo-ng. */

*** cnpatch/old/relay/fileart.c	Thu Aug 24 16:39:59 1989
--- relay/fileart.c	Mon Nov 27 19:47:53 1989
***************
*** 25,29 ****
--- 25,31 ----
  #include "news.h"
  #include "config.h"
+ #include "control.h"
  #include "active.h"
+ #include "fileart.h"
  #include "mkdirs.h"
  #include "headers.h"
***************
*** 32,38 ****
  #include "system.h"
  
- #define JUNK "junk"			/* lost+found pseudo-ng. */
- #define CONTROL "control"		/* control message pseudo-ng. */
- 
  static long artnum;			/* asgnartnum sets artnum */
  static int goodngs;			/* asgnartnum reads goodngs */
--- 34,37 ----
***************
*** 98,102 ****
  	register char *comma;
  
! 	ngs = (art->h.h_ctlcmd != NULL? CONTROL: art->h.h_ngs);
  	if (art->a_status&ST_REFUSED)
  		(void) fprintf(stderr,
--- 97,101 ----
  	register char *comma;
  
! 	ngs = (art->h.h_ctlcmd != NULL? CONTROL: art->h.h_ngs);	/* NCMP */
  	if (art->a_status&ST_REFUSED)
  		(void) fprintf(stderr,

*** cnpatch/old/relay/fileart.h	Tue Jun 20 19:01:12 1989
--- relay/fileart.h	Mon Nov 27 19:47:53 1989
***************
*** 2,3 ****
--- 2,5 ----
  extern void filedebug();
  extern void fileart();
+ 
+ #define JUNK "junk"			/* lost+found pseudo-ng. */

*** cnpatch/old/relay/hdrdefs.c	Tue Jun 20 19:01:16 1989
--- relay/hdrdefs.c	Mon Nov 27 19:47:53 1989
***************
*** 13,16 ****
--- 13,17 ----
  #include <stdlib.h>
  #endif				/* REALSTDC */
+ #include "libc.h"
  #include "news.h"
  #include "headers.h"
***************
*** 29,33 ****
  /* optional headers */
  static const char appnm[] =	"Approved:";	/* for mod. groups */
! static const char ctlnm[] =	"Control:";	/* ctl. msg. */
  static const char expnm[] =	"Expires:";	/* for history */
  static const char distrnm[] =	"Distribution:";	/* for transmission */
--- 30,35 ----
  /* optional headers */
  static const char appnm[] =	"Approved:";	/* for mod. groups */
! static const char ctlnm[] =	"Control:";	/* ctl. msg.; NCMP */
! static const char etctlnm[] =	"Also-Control:";	/* hybrid ctl. msg.; NCMP */
  static const char expnm[] =	"Expires:";	/* for history */
  static const char distrnm[] =	"Distribution:";	/* for transmission */
***************
*** 57,62 ****
  static const struct hdrdef apphdr = {
  	appnm, STRLEN(appnm), offsetof(struct headers, h_approved) };
! static const struct hdrdef ctlhdr = {
! 	ctlnm, STRLEN(ctlnm), offsetof(struct headers, h_ctlcmd) };
  static const struct hdrdef exphdr = {
  	expnm, STRLEN(expnm), offsetof(struct headers, h_expiry) };
--- 59,66 ----
  static const struct hdrdef apphdr = {
  	appnm, STRLEN(appnm), offsetof(struct headers, h_approved) };
! static const struct hdrdef ctlhdr = {					/* NCMP */
! 	ctlnm, STRLEN(ctlnm), offsetof(struct headers, h_ctlcmd) };	/* NCMP */
! static const struct hdrdef etctlhdr = {					/* NCMP */
! 	etctlnm, STRLEN(etctlnm), offsetof(struct headers, h_etctlcmd) }; /* NCMP */
  static const struct hdrdef exphdr = {
  	expnm, STRLEN(expnm), offsetof(struct headers, h_expiry) };
***************
*** 85,89 ****
  	/* start optional headers */
  	&apphdr,
! 	&ctlhdr,
  	&distrhdr,
  	&exphdr,
--- 89,94 ----
  	/* start optional headers */
  	&apphdr,
! 	&ctlhdr,		/* NCMP */
! 	&etctlhdr,		/* NCMP */
  	&distrhdr,
  	&exphdr,
***************
*** 109,110 ****
--- 114,156 ----
  
  boolean headdebug = NO;
+ 
+ void
+ hdrdebug(state)
+ int state;
+ {
+ 	headdebug = state;
+ }
+ 
+ void
+ hdrinit(hdrs)			/* zero all elements of hdrs */
+ register struct headers *hdrs;
+ {
+ 	hdrs->h_subj = NULL;
+ 	hdrs->h_ngs = NULL;
+ 	hdrs->h_distr = NULL;
+ 	hdrs->h_ctlcmd = NULL;		/* NCMP */
+ 	hdrs->h_etctlcmd = NULL;	/* NCMP */
+ 	hdrs->h_approved = NULL;
+ 	hdrs->h_msgid = NULL;
+ 	hdrs->h_artid = NULL;
+ 	hdrs->h_expiry = NULL;
+ 	hdrs->h_path = NULL;
+ 	hdrs->h_sender = NULL;
+ }
+ 
+ void
+ freeheaders(hdrs)		/* free (assumed) malloced storage */
+ register struct headers *hdrs;
+ {
+ 	nnfree(&hdrs->h_subj);
+ 	nnfree(&hdrs->h_ngs);
+ 	nnfree(&hdrs->h_distr);
+ 	nnfree(&hdrs->h_ctlcmd);	/* NCMP */
+ 	nnfree(&hdrs->h_etctlcmd);	/* NCMP */
+ 	nnfree(&hdrs->h_approved);
+ 	nnfree(&hdrs->h_msgid);
+ 	nnfree(&hdrs->h_artid);
+ 	nnfree(&hdrs->h_expiry);
+ 	nnfree(&hdrs->h_path);
+ 	nnfree(&hdrs->h_sender);
+ }

*** cnpatch/old/relay/hdrint.h	Thu Aug 24 16:39:59 1989
--- relay/hdrint.h	Mon Nov 27 19:47:53 1989
***************
*** 22,33 ****
  #define DEFMSGID ""		/* must be empty string or contain whitespace */
  
- #define JUNK "junk"
- #define ALL "all"
- 
- #ifdef SLOWCTLMATCH
- #define OLDCNTRL "all.all.ctl"
- #endif
- #define SFXOLDCNTRL ".ctl"
- 
  struct hdrdef {
  	const char *hdrnm;	/* ascii name */
--- 22,25 ----

*** cnpatch/old/relay/hdrparse.c	Mon Nov 13 17:39:50 1989
--- relay/hdrparse.c	Mon Nov 27 19:47:53 1989
***************
*** 7,11 ****
--- 7,13 ----
  #include "libc.h"
  #include "news.h"
+ #include "control.h"
  #include "case.h"
+ #include "fileart.h"
  #include "headers.h"
  #include "hdrint.h"
***************
*** 12,25 ****
  
  /*
-  * Reset internal state of header parser.
-  * (Empty the stomach of partially-digested headers.)
-  */
- void
- hdrwretch()
- {
- 	/* historical stub */
- }
- 
- /*
   * Parse (assumed) RFC822/850/1036 header in "line" (ishdr(line) can
   * verify this) into "hdrs" using hdrlst set of keywords by retaining the
--- 14,17 ----
***************
*** 32,39 ****
  hdrparse(hdrs, line, hdrlst)
  register struct headers *hdrs;
! register char *line;
  hdrlist hdrlst;				/* headers of positive utility */
  {
  	register struct hdrdef **hpp;
  
  	for (hpp = hdrlst; *hpp != NULL; hpp++) {
--- 24,32 ----
  hdrparse(hdrs, line, hdrlst)
  register struct headers *hdrs;
! char *line;
  hdrlist hdrlst;				/* headers of positive utility */
  {
  	register struct hdrdef **hpp;
+ 	register char *hackline = hackhybrid(line);
  
  	for (hpp = hdrlst; *hpp != NULL; hpp++) {
***************
*** 40,44 ****
  		register char *hdrnm = (*hpp)->hdrnm;
  
! 		if (CISTREQN(line, hdrnm, (int)(*hpp)->hdrlen) &&
  		    (*hpp)->hdroff >= 0)	/* paranoia */
  			break;
--- 33,37 ----
  		register char *hdrnm = (*hpp)->hdrnm;
  
! 		if (CISTREQN(hackline, hdrnm, (int)(*hpp)->hdrlen) &&
  		    (*hpp)->hdroff >= 0)	/* paranoia */
  			break;
***************
*** 48,55 ****
  
  		nnfree(ptrp);		/* free prev. value in this article */
! 		*ptrp = strsave(skipsp(&line[(*hpp)->hdrlen]));
  		if (*ptrp != NULL)
  			trim(*ptrp);		/* cut trailing \n */
  	}
  }
  
--- 41,49 ----
  
  		nnfree(ptrp);		/* free prev. value in this article */
! 		*ptrp = strsave(skipsp(&hackline[(*hpp)->hdrlen]));
  		if (*ptrp != NULL)
  			trim(*ptrp);		/* cut trailing \n */
  	}
+ 	free(hackline);
  }
  
***************
*** 90,94 ****
  	if (hdrs->h_subj == NULL)
  		hdrs->h_subj = strsave("");
! 	if (hdrs->h_ctlcmd == NULL && oldctl(hdrs))
! 		hdrs->h_ctlcmd = strsave(hdrs->h_subj);
  }
--- 84,87 ----
  	if (hdrs->h_subj == NULL)
  		hdrs->h_subj = strsave("");
! 	hackoldctl(hdrs);				/* NCMP */
  }

*** cnpatch/old/relay/headers.h	Tue Jun 20 19:01:19 1989
--- relay/headers.h	Mon Nov 27 19:47:54 1989
***************
*** 19,23 ****
  	char *h_ngs;	/* newsgroups: used in filing, sys matching & all.all.ctl matching */
  	char *h_distr;	/* distribution for transmit */
! 	char *h_ctlcmd;	/* control command */
  	char *h_approved;	/* needed for acceptance in moderated groups */
  	char *h_msgid;	/* needed for history & rejection */
--- 19,24 ----
  	char *h_ngs;	/* newsgroups: used in filing, sys matching & all.all.ctl matching */
  	char *h_distr;	/* distribution for transmit */
! 	char *h_ctlcmd;	/* control command (NCMP) */
! 	char *h_etctlcmd;	/* also-control command (NCMP) */
  	char *h_approved;	/* needed for acceptance in moderated groups */
  	char *h_msgid;	/* needed for history & rejection */
***************
*** 36,39 ****
  
  /* parse */
! extern void hdrwretch(), hdrparse(), hdrdeflt();
  extern boolean ishdr(), contin();
--- 37,40 ----
  
  /* parse */
! extern void hdrparse(), hdrdeflt();
  extern boolean ishdr(), contin();

*** cnpatch/old/relay/makefile	Mon Nov 13 17:39:53 1989
--- relay/makefile	Sat Dec 30 02:20:17 1989
***************
*** 33,41 ****
  LIBOBJS=../libcnews.a
  SRC=relaynews.c active.c article.c caches.c mkdirs.c control.c fileart.c \
! 	hdrdefs.c hdrcommon.c hdrparse.c hdrmunge.c \
  	history.c io.c msgs.c procart.c \
  	sys.c transmit.c trbatch.c ihave.c $(LIBSRCS)
  OBJ=relaynews.o active.o article.o caches.o mkdirs.o control.o fileart.o \
! 	hdrdefs.o hdrcommon.o hdrparse.o hdrmunge.o \
  	history.o io.o msgs.o procart.o \
  	sys.o transmit.o trbatch.o ihave.o
--- 33,41 ----
  LIBOBJS=../libcnews.a
  SRC=relaynews.c active.c article.c caches.c mkdirs.c control.c fileart.c \
! 	hdrdefs.c hdrparse.c hdrmunge.c \
  	history.c io.c msgs.c procart.c \
  	sys.c transmit.c trbatch.c ihave.c $(LIBSRCS)
  OBJ=relaynews.o active.o article.o caches.o mkdirs.o control.o fileart.o \
! 	hdrdefs.o hdrparse.o hdrmunge.o \
  	history.o io.o msgs.o procart.o \
  	sys.o transmit.o trbatch.o ihave.o
***************
*** 80,84 ****
  cmp:	relaynews
  	cmp $(NEWSBIN)/relay/relaynews relaynews
- 	ls -lg $(NEWSBIN)/relay/relaynews | egrep -s '^-rwsrwsr-x  1 news     news'
  	for f in `ls sh` ; do cmp $(NEWSBIN)/inject/$$f sh/$$f ; done
  	for f in `ls ctl` ; do cmp $(NEWSBIN)/ctl/$$f ctl/$$f ; done
--- 80,83 ----
***************
*** 85,89 ****
--- 84,97 ----
  	for f in `ls aux` ; do cmp $(NEWSBIN)/relay/$$f aux/$$f ; done
  	cmp $(BIN)/inews sh/inews
+ 	ls -lg $(NEWSBIN)/relay/relaynews | egrep -s '^-rwsrwsr-x  1 news     news'
  
+ check:	relaynews
+ 	cmp $(NEWSBIN)/relay/relaynews relaynews || true
+ 	for f in `ls sh` ; do cmp $(NEWSBIN)/inject/$$f sh/$$f || true ; done
+ 	for f in `ls ctl` ; do cmp $(NEWSBIN)/ctl/$$f ctl/$$f || true ; done
+ 	for f in `ls aux` ; do cmp $(NEWSBIN)/relay/$$f aux/$$f || true ; done
+ 	cmp $(BIN)/inews sh/inews || true
+ 	ls -lg $(NEWSBIN)/relay/relaynews | egrep -s '^-rwsrwsr-x  1 news     news'
+ 
  TODO.grep: TODO
  	-egrep TODO ../include/*.h *.h *.c sh/* | tr -s " \11" " " >$@
***************
*** 124,128 ****
  fileart.o: ../include/libc.h ../include/news.h ../include/config.h
  fileart.o: active.h mkdirs.h headers.h article.h history.h system.h
- hdrcommon.o: ../include/news.h headers.h hdrint.h
  hdrdefs.o: ../include/news.h headers.h hdrint.h
  hdrmunge.o: ../include/libc.h ../include/news.h fileart.h headers.h
--- 132,135 ----

*** cnpatch/old/relay/procart.c	Mon Nov 13 17:39:53 1989
--- relay/procart.c	Mon Nov 27 19:47:54 1989
***************
*** 136,144 ****
  {
  	register char *hdr = NULL;
! 	long limit;
  	int is_hdr = NO;
  
- 	hdrwretch();				/* reset the header parser */
- 	limit = (art->a_blvmax? art->a_unread+1: art->a_unread); /* 1 for NUL */
  	/* 1 is again for NUL */
  	while (limit > 1 && (hdr = gethdr(in, &limit, &is_hdr)) != NULL && is_hdr) {
--- 136,142 ----
  {
  	register char *hdr = NULL;
! 	long limit = (art->a_blvmax? art->a_unread+1: art->a_unread); /* 1 for NUL */
  	int is_hdr = NO;
  
  	/* 1 is again for NUL */
  	while (limit > 1 && (hdr = gethdr(in, &limit, &is_hdr)) != NULL && is_hdr) {
***************
*** 274,279 ****
  		transmit(art, exclude);		/* writes systems on stdout */
  		(void) putchar('\n');		/* ends the log line */
! 		if (art->h.h_ctlcmd != NULL)
! 			ctlmsg(art);
  #ifdef notdef					/* it's only a log file! */
  		(void) fflush(stdout);		/* crash-proofness */
--- 272,276 ----
  		transmit(art, exclude);		/* writes systems on stdout */
  		(void) putchar('\n');		/* ends the log line */
! 		ctlmsg(art);
  #ifdef notdef					/* it's only a log file! */
  		(void) fflush(stdout);		/* crash-proofness */

*** cnpatch/old/relay/transmit.c	Thu Aug 24 16:40:07 1989
--- relay/transmit.c	Tue Dec 19 16:07:22 1989
***************
*** 178,182 ****
  		STRLEN(":") + strlen(bincmd) + STRLEN(":") + strlen(newspath()) +
  		STRLEN(";<") + strlen(filename) + STRLEN(" (") +
! 		strlen(syscmd) + strlen(filename) + STRLEN(")") + 1));
  	(void) strcpy(cmd, "PATH=");
  	(void) strcat(cmd, ctlcmd);
--- 178,182 ----
  		STRLEN(":") + strlen(bincmd) + STRLEN(":") + strlen(newspath()) +
  		STRLEN(";<") + strlen(filename) + STRLEN(" (") +
! 		strlen(syscmd) + strlen(filename) + STRLEN(")") + SIZENUL));
  	(void) strcpy(cmd, "PATH=");
  	(void) strcat(cmd, ctlcmd);
***************
*** 199,207 ****
  			art->a_status |= ST_DROPPED;
  			(void) fprintf(stderr, "%s: `%s' contains two %%'s\n",
! 				progname, cmd);
  		} else if (*percent != 's' && *percent != '%') {
  			art->a_status |= ST_DROPPED;
  			(void) fprintf(stderr, "%s: `%s' contains %%%c, not %%s\n",
! 				progname, cmd, *percent);
  		} else
  			(void) sprintf(cmd+strlen(cmd), syscmd, filename);
--- 199,207 ----
  			art->a_status |= ST_DROPPED;
  			(void) fprintf(stderr, "%s: `%s' contains two %%'s\n",
! 				progname, syscmd);
  		} else if (*percent != 's' && *percent != '%') {
  			art->a_status |= ST_DROPPED;
  			(void) fprintf(stderr, "%s: `%s' contains %%%c, not %%s\n",
! 				progname, syscmd, *percent);
  		} else
  			(void) sprintf(cmd+strlen(cmd), syscmd, filename);
***************
*** 211,216 ****
  	if (exitstat != 0) {
  		art->a_status |= ST_DROPPED;
! 		(void) fprintf(stderr, "%s: `%s' returned exit status 0%o\n",
! 			progname, cmd, exitstat);
  	}
  	free(cmd);
--- 211,217 ----
  	if (exitstat != 0) {
  		art->a_status |= ST_DROPPED;
! 		(void) fprintf(stderr, "%s: `", progname);
! 		(void) fputs(cmd, stderr);
! 		(void) fprintf(stderr, "' returned exit status 0%o\n", exitstat);
  	}
  	free(cmd);

Files that are new:

new libfake/dbmclose.c (patch can't create, so diff against null):
Index: libfake/dbmclose.c
*** cnpatch/old/libfake/dbmclose.c	Wed Jan 10 18:03:50 1990
--- libfake/dbmclose.c	Tue Nov 28 19:20:22 1989
***************
*** 0 ****
--- 1 ----
+ dbmclose(){}

new notebook/problems (patch can't create, so diff against null):
Index: notebook/problems
*** cnpatch/old/notebook/problems	Wed Jan 10 18:03:51 1990
--- notebook/problems	Wed Jan 10 17:54:42 1990
***************
*** 0 ****
--- 1,145 ----
+ .DA "31 Dec 1989"
+ .TL
+ Known Porting Problems With C News
+ .AU
+ Henry Spencer
+ .AI
+ Dept. of Zoology
+ University of Toronto
+ .SH
+ Intro
+ .PP
+ C News in general is pretty portable.
+ People have got it to run on a very wide range of systems with little
+ trouble.
+ Difficulties are usually problems in the system, not C News.
+ Some of them, however, are widespread enough to be worth comment, for
+ the guidance of people having problems.
+ If you run into a novel problem,
+ we are always interested in hearing about such things.
+ .SH
+ Unix Dependencies
+ .PP
+ The biggest portability glitch in C News is that it depends a lot on Unix
+ utilities.
+ The extensive use of complex shell files, \fIsed\fR and \fIawk\fR programs,
+ and a wide range of lesser Unix utilities would make it quite difficult
+ to move C News to a system that is seriously non-Unix-like.
+ The actual C programs seldom depend on Unix in major ways.
+ (An exception is the use
+ of \fIread\fR system calls in \fIexpire\fR, to avoid difficulties with
+ stdio end-of-file behavior;
+ we now know how to avoid this but haven't implemented the fixes yet.)
+ .PP
+ We know that \fIawk\fR and the colon (:) operator of \fIexpr\fR are
+ problem areas under Minix.
+ .SH
+ Shell Problems
+ .PP
+ C News seriously stress-tests shells.
+ The current Minix shell is not robust enough
+ in the face of complex inputs, botches some constructs entirely,
+ and can run out of memory on the complex shell files.
+ Any shell that is too old to implement comments begun
+ by ``#'' is big trouble, since we use such comments everywhere.
+ .PP
+ Any system/shell combination that thinks that a shell script starting
+ with ``#!\ /bin/sh'' should be run by the C Shell (because it starts
+ with `#') is also big trouble:
+ you will have to change that line to ``:\ use\ /bin/sh'' everywhere.
+ We know that at least some releases of Xenix have this problem.
+ It is not necessary that your kernel understand the ``#!'' feature\(emwe
+ believe that nothing in C News relies on it\(embut it is essential that
+ it not cause invocation of the C Shell.
+ .PP
+ We know that some Hewlett-Packard Unixes have broken shells, probably
+ the result of mistakes in
+ HP's efforts to make
+ the shell 8-bit-clean; the symptom is
+ that something like:
+ .DS
+ x=y
+ if test " $x" != " y"
+ then
+ 	echo oops
+ fi
+ .DE
+ prints ``oops''.
+ This is, again, big trouble, because we do that a lot.
+ .PP
+ Many people using 3B1s, aka UNIX PCs,
+ run the Korn shell as their \fI/bin/sh\fR.
+ Some other folks may do this too.
+ Beware that \fIksh\fR was not fully \fIsh\fR-compatible for a
+ long time, with some subtle differences in the
+ ill-documented behavior of backquotes and backslashes.
+ Some of the C News shell scripts,
+ notably \fIinews\fR,
+ are known to hit these bugs.
+ We are \fItold\fR that current \fIksh\fRs have fixed them.
+ .SH
+ Make vs. Test
+ .PP
+ There is a persistent problem on 3B2s with implementations of \fImake\fR
+ that violate the SVID in a subtle way.
+ They attempt to execute makefile commands directly, rather than via the
+ shell, if the commands do not contain metacharacters.
+ This means that if\(emas on many 3B2s\(em\fItest\fR is a shell builtin
+ \fIand there is no /bin/test program\fR, the makefile line
+ ``test\ \-s\ file'' will cause \fImake\fR to complain about an unknown
+ command.
+ (The SVID says that makefile commands must be executed as if by
+ the shell, and the shell will execute this line correctly.)
+ We've added `;' on the ends of such lines, which suffices to convince
+ \fImake\fR to run a shell on the systems we've encountered, but AT&T
+ is good at finding ways to break such workarounds.
+ This problem is also known to occur in A/UX.
+ .SH
+ Offsetof
+ .PP
+ ANSI C requires C compilers to supply a macro \fIoffsetof\fR, which can
+ be used to find the offset of a structure member within the structure.
+ \fIRelaynews\fR's header-parsing code uses it,
+ defining it if the system has not supplied it.
+ Unfortunately, it is really hard to write a portable version of this.
+ The implementation we currently use is:
+ .DS
+ #define offsetof(type, mem) ((char *)&((type *)NULL)\->mem \- (char *)NULL)
+ .DE
+ The table in \fIrelay/hdrdefs.c\fR
+ puts invocations of \fIoffsetof\fR in initializers.
+ This turns out to be a severe stress test for C compilers.
+ A compilation error in \fIhdrdefs.c\fR is almost certain
+ to be problems with this macro.
+ Some compilers,
+ notably the one in Microport System V Release 2.3,
+ reject it.
+ We have heard a report that System V Release 2 on the VAX silently
+ miscompiles it!
+ If you have trouble with \fIoffsetof\fR, you might try this version instead:
+ .DS
+ #define offsetof(type, mem) ((int)&((type *)NULL)\->mem)
+ .DE
+ .SH
+ Fast Stdio Routines
+ .PP
+ We supply a set of fast standard-I/O routines that are compatible with
+ most AT&T-derived implementations of \fIstdio\fR.
+ They speed up C News quite a bit.
+ However, they don't work on all Unixes.
+ The tester program we supply, which the library-build procedure runs,
+ is thought to diagnose such problems 100% of the time.
+ It has been reported in the past that A/UX and Microport 386 stdios
+ flunk the test.
+ SunOS 4.0 used to pass the test falsely, but improvements in both
+ the test and the routines
+ seem to have cured the problems:
+ 4.0.3 passes the test and
+ as far as we can tell,
+ the routines run correctly under it.
+ .PP
+ In any case, if you are feeling nervous or are having mysterious problems,
+ telling \fIbuild\fR that you don't want to use the fast-stdio stuff is
+ always safe.
+ .PP
+ xxx more to come...


end of patch 10-Jan-1990