[news.software.b] 24-Aug-1989 patch for C News, including updatemin fix

henry@utzoo.uucp (Henry Spencer) (08/25/89)

Well, I'd hoped that this one would have more substantive content.  Alas,
some more minor cleanup work touched a lot of files, and through the magic
of context diffs :-( we're already up to one patch worth.

More minor cleanup and improvements.  Build now asks about linking flags
in addition to compiling flags (most people get along by using the same
flags for both, but there have been requests).  Index/rindex have been
changed to strchr/strrchr everywhere, to standardize.  The -r option of
expire is now documented, and doexpire is now willing to use it if space
looks tight.  Relaynews now rejects articles with white space in their
message-id -- this is illegal by both RFCs and bothers some other software
badly, and we prefer rejecting stuff outright to quietly "fixing things"
without telling people about it.  URGENT BUG FIX FOR UPDATEMIN.  And the
beginnings of case-insensitive header-name recognition (Geoff suspects
you can interpret RFC1036 to the effect that this is unnecessary, but
the ice is thin there, so we're going to do it).

start of patch 24-Aug-1989
this should be run with   patch -p0 <thisfile

Please do the following (there is no easy way we can convince
patch to do this automatically):
rm libfake/index.c
rm libfake/rindex.c

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
*** tmp.dates.with.really.long.filename.for.patch	Thu Aug 24 15:38:53 1989
--- PATCHDATES	Thu Aug 24 15:38:53 1989
***************
*** 1,4 ****
--- 1,5 ----
  23-Jun-1989
  7-Jul-1989
  23-Jul-1989
  22-Aug-1989
+ 24-Aug-1989

Changed files, if any:

*** cnpatch/tmp.file	Thu Aug 24 15:39:02 1989
--- batch/Makefile	Tue Aug 22 16:56:12 1989
***************
*** 1,7 ****
  # Configuration stuff.
  COPTS=-O
  CFLAGS=$(COPTS) -I../include
- LDFLAGS=
  LIBS=../libcnews.a
  # =()<NEWSARTS = @<NEWSARTS>@>()=
  NEWSARTS = /usr/spool/news
--- 1,6 ----
***************
*** 33,39 ****
  	$(CC) $(CFLAGS) $(LDFLAGS) c7encode.o $(PRE) $(LIBS) $(POST) -o $@
  
  bencode:	bencode.o crctab.o $(LIBS)
! 	$(CC) $(CFLAGS) bencode.o crctab.o $(PRE) $(LIBS) $(POST) -o $@
  
  bencode.o:	coder.h
  
--- 32,38 ----
  	$(CC) $(CFLAGS) $(LDFLAGS) c7encode.o $(PRE) $(LIBS) $(POST) -o $@
  
  bencode:	bencode.o crctab.o $(LIBS)
! 	$(CC) $(CFLAGS) $(LDFLAGS) bencode.o crctab.o $(PRE) $(LIBS) $(POST) -o $@
  
  bencode.o:	coder.h
  

*** cnpatch/tmp.file	Thu Aug 24 15:39:09 1989
--- conf/Makefile	Tue Aug 22 16:54:25 1989
***************
*** 77,83 ****
  	echo 'echo 0' >>$@
  
  setnewsids:	setnewsids.o $(LIBS)
! 	$(CC) $(CFLAGS) setnewsids.o $(PRE) $(LIBS) $(POST) -o $@
  
  ../ranlibed:	../libcnews.a
  	ranlib ../libcnews.a
--- 77,83 ----
  	echo 'echo 0' >>$@
  
  setnewsids:	setnewsids.o $(LIBS)
! 	$(CC) $(CFLAGS) $(LDFLAGS) setnewsids.o $(PRE) $(LIBS) $(POST) -o $@
  
  ../ranlibed:	../libcnews.a
  	ranlib ../libcnews.a

*** cnpatch/tmp.file	Thu Aug 24 15:39:11 1989
--- conf/build	Wed Aug 23 15:59:12 1989
***************
*** 1,8 ****
  #! /bin/sh
  
  # functions and headers we are prepared to fake
! mightfake='fsync getopt index memcpy memcmp memchr memset mkdir
! 	putenv rindex strchr strrchr strpbrk strspn strcspn strtok symlink'
  mightfakehdrs='stdlib.h string.h'
  
  # directories in which to do makes
--- 1,8 ----
  #! /bin/sh
  
  # functions and headers we are prepared to fake
! mightfake='fsync getopt memcpy memcmp memchr memset mkdir
! 	putenv strchr strrchr strpbrk strspn strcspn strtok symlink'
  mightfakehdrs='stdlib.h string.h'
  
  # directories in which to do makes
***************
*** 263,268 ****
--- 263,270 ----
  	echo "umask $newsumask"
  	echo 'set -x'
  	echo ": making directories..."
+ 	ln=
+ 	lb=
  	if test " $makelinks" = " y"
  	then
  		echo "mkdir $realarts $realctl $realbin"
***************
*** 269,282 ****
--- 271,287 ----
  		if test " $realarts" != " $newsarts"
  		then
  			echo "ln -s $realarts $newsarts"
+ 			ln="$ln $realarts"
  		fi
  		if test " $realctl" != " $newsctl"
  		then
  			echo "ln -s $realctl $newsctl"
+ 			ln="$ln $realctl"
  		fi
  		if test " $realbin" != " $newsbin"
  		then
  			echo "ln -s $realbin $newsbin"
+ 			lb="$lb $realbin"
  		fi
  	fi
  	n="$newsarts $newsarts/in.coming $newsarts/in.coming/bad"
***************
*** 291,303 ****
  	echo "done"
  	if test " $chboth" = " y"
  	then
! 		echo "$chown $newsuid.$newsgid $n"
! 		echo "$chown $binuid.$bingid $b"
  	else
! 		echo "$chown $newsuid $n"
! 		echo "$chgrp $newsgid $n"
! 		echo "$chown $binuid $b"
! 		echo "$chgrp $bingid $b"
  	fi
  	echo ": done"
  ) >>doit.root
--- 296,308 ----
  	echo "done"
  	if test " $chboth" = " y"
  	then
! 		echo "$chown $newsuid.$newsgid $n $ln"
! 		echo "$chown $binuid.$bingid $b $lb"
  	else
! 		echo "$chown $newsuid $n $ln"
! 		echo "$chgrp $newsgid $n $ln"
! 		echo "$chown $binuid $b $lb"
! 		echo "$chgrp $bingid $b $lb"
  	fi
  	echo ": done"
  ) >>doit.root
***************
*** 416,422 ****
  found=
  for f in $fake dummy
  do
! 	if test " $f" = " index.o"
  	then
  		found=y
  	fi
--- 421,427 ----
  found=
  for f in $fake dummy
  do
! 	if test " $f" = " strchr.o"
  	then
  		found=y
  	fi
***************
*** 424,435 ****
  if test " $found" = " "
  then
  	echo
! 	echo 'A well-tuned index() function customized to a particular machine'
! 	echo 'is usually faster than portable C.  Is your index() function'
  	./query 'indeed fast (okay to guess) [yes]? '
! 	read fastindex
! 	case "$fastindex" in
! 	y*|Y*|'')	fastindex=y	;;
  	esac
  fi
  
--- 429,440 ----
  if test " $found" = " "
  then
  	echo
! 	echo 'A well-tuned strchr() function customized to a particular machine'
! 	echo 'is usually faster than portable C.  Is your strchr() function'
  	./query 'indeed fast (okay to guess) [yes]? '
! 	read faststrchr
! 	case "$faststrchr" in
! 	y*|Y*|'')	faststrchr=y	;;
  	esac
  fi
  
***************
*** 528,533 ****
--- 533,549 ----
  esac
  
  echo
+ echo 'The final linking ("ld") step of compiling might need an option,'
+ echo 'such as -n or -i, to produce the preferred form of executable file.'
+ echo 'On many modern systems the preferred form is the default.  What options,'
+ ./query 'if any, should be given for linking [none]? '
+ read ldopts
+ case "$ldopts" in
+ '')	;;
+ *)	copts="$copts LDFLAGS='$ldopts'"	;;
+ esac
+ 
+ echo
  echo 'On unusual systems it may be necessary to link C News programs with'
  echo 'libraries other than the usual C library.  These can be specified as'
  echo 'either full pathnames or -l... options.  What libraries, in addition'
***************
*** 847,855 ****
  	echo 'fi'
  	echo 'cd h'
  	echo 'rm -f nnewshsed'
! 	if test " $fastindex" != " y"
  	then
! 		echo 'echo "/FASTINDEX.*qqq/s;^;/* ;" >>nnewshsed'
  	fi
  	if test " $storeval" = " y"
  	then
--- 863,871 ----
  	echo 'fi'
  	echo 'cd h'
  	echo 'rm -f nnewshsed'
! 	if test " $faststrchr" != " y"
  	then
! 		echo 'echo "/FASTSTRCHR.*qqq/s;^;/* ;" >>nnewshsed'
  	fi
  	if test " $storeval" = " y"
  	then

*** cnpatch/tmp.file	Thu Aug 24 15:39:17 1989
--- conf/sys.proto	Tue Aug 22 16:20:54 1989
***************
*** 4,9 ****
--- 4,12 ----
  # sample insignificant feed not using batching
  huey:news.config,to.huey/all::uux - -r -gd huey!rnews
  
+ # sample of mailing newsgroups to someone (note distribution)
+ daisy:soc.women,soc.couples/all::mail daisy@duck
+ 
  # sample major batched feed, including (unnecessary) explicit file name
  dewey:comp,news,sci,rec,misc,soc,talk,to.dewey,can,ont,tor,ut/all:f:dewey/togo
  

*** cnpatch/tmp.file	Thu Aug 24 15:39:32 1989
--- expire/Makefile	Thu Aug 24 14:52:30 1989
***************
*** 3,9 ****
  CFLAGS = $(COPTS) -I../include $(PROF)
  LINTFLAGS = -I../include
  JUNKLINT = 'possible pointer align'
- LDFLAGS = $(CFLAGS)
  DBM = -ldbm
  LIBS= ../libcnews.a
  THEM = expire histdups histinfo histslash mkdbm mkhistory \
--- 3,8 ----
***************
*** 35,53 ****
  	-if test ! -r $(NEWSCTL)/explist ; then cp explist.proto $(NEWSCTL)/explist ; fi
  
  expire: expire.o $(LIBS)
! 	$(CC) $(LDFLAGS) expire.o $(PRE) $(LIBS) $(DBM) $(POST) -o $@
  
  histinfo: histinfo.o $(LIBS)
! 	$(CC) $(LDFLAGS) histinfo.o $(PRE) $(LIBS) $(POST) -o $@
  
  updatemin:	updatemin.o $(LIBS)
! 	$(CC) $(LDFLAGS) updatemin.o $(PRE) $(LIBS) $(POST) -o $@
  
  histslash:	histslash.o $(LIBS)
! 	$(CC) $(LDFLAGS) histslash.o $(PRE) $(LIBS) $(POST) -o $@
  
  mkdbm:	mkdbm.o $(LIBS)
! 	$(CC) $(LDFLAGS) mkdbm.o $(PRE) $(LIBS) $(DBM) $(POST) -o $@
  
  lint:	expire.c
  	lint -ha $(LINTFLAGS) expire.c 2>&1 | egrep -v $(JUNKLINT) | tee $@
--- 34,52 ----
  	-if test ! -r $(NEWSCTL)/explist ; then cp explist.proto $(NEWSCTL)/explist ; fi
  
  expire: expire.o $(LIBS)
! 	$(CC) $(CFLAGS) $(LDFLAGS) expire.o $(PRE) $(LIBS) $(DBM) $(POST) -o $@
  
  histinfo: histinfo.o $(LIBS)
! 	$(CC) $(CFLAGS) $(LDFLAGS) histinfo.o $(PRE) $(LIBS) $(POST) -o $@
  
  updatemin:	updatemin.o $(LIBS)
! 	$(CC) $(CFLAGS) $(LDFLAGS) updatemin.o $(PRE) $(LIBS) $(POST) -o $@
  
  histslash:	histslash.o $(LIBS)
! 	$(CC) $(CFLAGS) $(LDFLAGS) histslash.o $(PRE) $(LIBS) $(POST) -o $@
  
  mkdbm:	mkdbm.o $(LIBS)
! 	$(CC) $(CFLAGS) $(LDFLAGS) mkdbm.o $(PRE) $(LIBS) $(DBM) $(POST) -o $@
  
  lint:	expire.c
  	lint -ha $(LINTFLAGS) expire.c 2>&1 | egrep -v $(JUNKLINT) | tee $@
***************
*** 111,117 ****
  	echo 'bletch 00099 00100 y' >>active.after
  	echo '<wont1>	9999~-	foo/1' >>history.proto
  	echo :foo/1: >arts/foo/1
! 	echo 'Message-ID: <wont1>' >>arts/foo/1
  	echo '<will2>	1000~-	foo/2' >>history.proto
  	echo foo/2 >arts/foo/2
  	echo '<will3>	1000~100	foo/3' >>history.proto
--- 110,116 ----
  	echo 'bletch 00099 00100 y' >>active.after
  	echo '<wont1>	9999~-	foo/1' >>history.proto
  	echo :foo/1: >arts/foo/1
! 	echo 'MeSsAge-ID: <wont1>' >>arts/foo/1
  	echo '<will2>	1000~-	foo/2' >>history.proto
  	echo foo/2 >arts/foo/2
  	echo '<will3>	1000~100	foo/3' >>history.proto
***************
*** 118,124 ****
  	echo foo/3 >arts/foo/3
  	echo '<two4>	100	bar/4' >>history.proto
  	echo :bar/4: >arts/bar/4
! 	echo 'Subject: yes' >>arts/bar/4
  	echo '<will5>	100~	bar.ugh/5' >>history.proto
  	echo :bar/ugh/5: >arts/bar/ugh/5
  	echo >>arts/bar/ugh/5
--- 117,123 ----
  	echo foo/3 >arts/foo/3
  	echo '<two4>	100	bar/4' >>history.proto
  	echo :bar/4: >arts/bar/4
! 	echo 'SuBjeCt: yes' >>arts/bar/4
  	echo '<will5>	100~	bar.ugh/5' >>history.proto
  	echo :bar/ugh/5: >arts/bar/ugh/5
  	echo >>arts/bar/ugh/5
***************
*** 127,134 ****
  	echo urp/6 >arts/urp/6
  	echo '<wont7>	9999~9999~xx~a	urp/7' >>history.proto
  	echo :urp/7: >arts/urp/7
! 	echo 'Message-ID: <wont7>' >>arts/urp/7
! 	echo 'Expires: 9999' >>arts/urp/7
  	echo '<gone8>	100~20000	urp/8' >>history.proto
  	echo urp/8 >arts/urp/8
  	echo '<gone9>	100~-	urp/9' >>history.proto
--- 126,133 ----
  	echo urp/6 >arts/urp/6
  	echo '<wont7>	9999~9999~xx~a	urp/7' >>history.proto
  	echo :urp/7: >arts/urp/7
! 	echo 'mEssaGe-id: <wont7>' >>arts/urp/7
! 	echo 'exPiRes: 9999' >>arts/urp/7
  	echo '<gone8>	100~20000	urp/8' >>history.proto
  	echo urp/8 >arts/urp/8
  	echo '<gone9>	100~-	urp/9' >>history.proto
***************
*** 213,218 ****
--- 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"

*** cnpatch/tmp.file	Thu Aug 24 15:39:35 1989
--- expire/doexpire	Wed Aug 23 15:36:16 1989
***************
*** 19,54 ****
  	exit 1
  fi
  
! cd $NEWSCTL
  
! firstctl=
! firstar=
! while true
  do
  	size="`sizeof history history.pag history.dir`"
! 	if test " `spacefor $size control`" -le 0
  	then
! 		if test " $firstctl" = " "
! 		then
! 			echo "$0: trouble finding space for work files" |
! 							mail "$NEWSMASTER"
! 			firstctl=n
! 		fi
! 	elif test " `spacefor 1 archive`" -le 0
! 	then
! 		if test " $firstar" = " "
! 		then
! 			echo "$0: trouble finding space for archiving" |
! 							mail "$NEWSMASTER"
! 			firstar=n
! 		fi
! 	else			# enough space both places
  		break
  	fi
  	sleep 600		# and hope it will improve
  done
  
! expire $* $NEWSCTL/explist 2>/tmp/doex$$
  if test -s /tmp/doex$$
  then
  	(echo 'expire problems:' ; cat /tmp/doex$$ ) | mail "$NEWSMASTER"
--- 19,49 ----
  	exit 1
  fi
  
! if test " `spacefor 1 archive`" -le 0
! then
! 	echo "$0: not enough space for archiving" | mail "$NEWSMASTER"
! 	exit 1
! fi
  
! cd $NEWSCTL
! ropt=-r
! for counter in x x x x		# four tries
  do
  	size="`sizeof history history.pag history.dir`"
! 	if test " `spacefor $size control`" -gt 0
  	then
! 		ropt=
  		break
  	fi
  	sleep 600		# and hope it will improve
  done
+ if test " $ropt" = " -r"
+ then
+ 	echo "$0: short of space for temporaries, resorting to \`expire -r'" |
+ 							mail "$NEWSMASTER"
+ fi
  
! expire $ropt $* $NEWSCTL/explist 2>/tmp/doex$$
  if test -s /tmp/doex$$
  then
  	(echo 'expire problems:' ; cat /tmp/doex$$ ) | mail "$NEWSMASTER"

*** cnpatch/tmp.file	Thu Aug 24 15:39:35 1989
--- expire/expire.c	Wed Aug 23 16:37:14 1989
***************
*** 19,24 ****
--- 19,25 ----
  #include "news.h"
  #include "config.h"
  #include "fgetmfs.h"
+ #include "case.h"
  
  #ifndef EPOCH
  #define	EPOCH	((time_t)0)
***************
*** 213,218 ****
--- 214,221 ----
  	if (expdebug)
  		setbuf(stderr, (char *)NULL);
  
+ 	(void) cistrncmp("a", "a", 1);		/* prime case.c */
+ 
  	if (optind < argc) {
  		cf = eufopen(argv[optind], "r");
  		control(cf);
***************
*** 905,911 ****
  	len = strlen(sline);
  	limit = buf + bsize - len;
  	for (scan = buf; scan < limit; scan++)
! 		if (STREQN(scan, sline, len) &&
  				(scan == buf || *(scan-1) == '\n')) {
  			scan += len;
  			for (limit = scan; limit < buf+bsize; limit++)
--- 908,914 ----
  	len = strlen(sline);
  	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;
  			for (limit = scan; limit < buf+bsize; limit++)

*** cnpatch/tmp.file	Thu Aug 24 15:39:38 1989
--- expire/histinfo.c	Wed Aug 23 16:27:50 1989
***************
*** 6,13 ****
  #include <sys/types.h>
  #include <sys/stat.h>		/* for modified time (date received) */
  #include "config.h"
  
- #define MAXLINE 1024
  #define STRLEN(s) (sizeof(s) - 1)	/* s must be a char array */
  
  char *progname;
--- 6,15 ----
  #include <sys/types.h>
  #include <sys/stat.h>		/* for modified time (date received) */
  #include "config.h"
+ #include "fgetmfs.h"
+ #include "alloc.h"
+ #include "case.h"
  
  #define STRLEN(s) (sizeof(s) - 1)	/* s must be a char array */
  
  char *progname;
***************
*** 28,34 ****
  	int c;
  	int errflg = 0;
  	FILE *in;
! 	char inname[MAXLINE];
  	extern int optind;
  	extern char *optarg;
  
--- 30,36 ----
  	int c;
  	int errflg = 0;
  	FILE *in;
! 	char *inname;
  	extern int optind;
  	extern char *optarg;
  
***************
*** 50,60 ****
  	spdir = artfile((char *)NULL);
  	spdirlen = strlen(spdir);
  	
! 	while (fgets(inname, sizeof(inname), stdin) != NULL) {
  		inname[strlen(inname)-1] = '\0';	/* kill newline */
  		in = efopen(inname, "r");
  		process(in, inname);
  		(void) fclose(in);
  	}
  	exit(0);
  }
--- 52,63 ----
  	spdir = artfile((char *)NULL);
  	spdirlen = strlen(spdir);
  	
! 	while ((inname = fgetms(stdin)) != NULL) {
  		inname[strlen(inname)-1] = '\0';	/* kill newline */
  		in = efopen(inname, "r");
  		process(in, inname);
  		(void) fclose(in);
+ 		free(inname);
  	}
  	exit(0);
  }
***************
*** 66,95 ****
  FILE *in;
  char *inname;
  {
! 	char *nl, *name;
! 	char line[MAXLINE], msgid[MAXLINE], expiry[MAXLINE];
! 	char datercv[30];
  	struct stat statb;
  	static char msgidnm[] =  "Message-ID: ";
  	static char expnm[] =    "Expires: ";
  	register char *p;
- 	static char trash[] = "<swill@trash>";
- 	extern char *strrchr();
  	extern char *strchr();
- 	extern char *strcpy();
  
! 	/* set defaults */
! 	(void) strcpy(expiry, "-");
! 	(void) strcpy(msgid, trash);
  
  	/* read until EOF or blank line (end of headers) */
! 	while (fgets(line, sizeof line, in) != NULL && strcmp(line, "\n") != 0) {
! 		if ((nl = strrchr(line, '\n')) != NULL)
! 			*nl = '\0';			/* trim newline */
! 		if (strncmp(line, msgidnm, STRLEN(msgidnm)) == 0)
! 			(void) strcpy(msgid, line+STRLEN(msgidnm));
! 		else if (strncmp(line, expnm, STRLEN(expnm)) == 0)
! 			(void) strcpy(expiry, line+STRLEN(expnm));
  	}
  
  	/* generate the file name */
--- 69,100 ----
  FILE *in;
  char *inname;
  {
! 	char *name;
! 	char *line;
! 	char *msgid;
! 	char *expiry;
! 	time_t datercv;
  	struct stat statb;
  	static char msgidnm[] =  "Message-ID: ";
  	static char expnm[] =    "Expires: ";
  	register char *p;
  	extern char *strchr();
  
! 	expiry = strsave("-");
! 	msgid = NULL;
  
  	/* read until EOF or blank line (end of headers) */
! 	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));
! 		}
! 		free(line);
  	}
  
  	/* generate the file name */
***************
*** 100,127 ****
  
  	/* generate the date received */
  	(void) fstat(fileno(in), &statb);
! 	(void) sprintf(datercv, "%ld", statb.st_mtime);
  
- 	/* de-tab the message id */
- 	for (p = strchr(msgid, '\t'); p != NULL; p = strchr(p, '\t'))
- 		*p = ' ';
- 
  	/* deal with empty and trash articles */
! 	if (strcmp(msgid, trash) == 0) {
! 		(void) sprintf(msgid, "<%s@trash>", name);
! 		(void) sprintf(datercv, "0");		/* expire at once */
  	}
  
  	/* whomp out the history line */
  	(void) fputs(msgid, stdout);
! 	(void) putchar('\t');
! 	(void) fputs(datercv, stdout);
! 	(void) putchar('~');
  	(void) fputs(expiry, stdout);
  	(void) putchar('\t');
  	(void) fputs(name, stdout);
  	(void) putchar('\n');
  	(void) fflush(stdout);
  }
  
  /*
--- 105,132 ----
  
  	/* generate the date received */
  	(void) fstat(fileno(in), &statb);
! 	datercv = statb.st_mtime;
  
  	/* deal with empty and trash articles */
! 	if (msgid == NULL || strchr(msgid, '\t') != NULL) {
! 		if (msgid != NULL)
! 			free(msgid);
! 		msgid = str3save("<", name, "@trash>");
! 		datercv = 0;
! 		free(expiry);
! 		expiry = strsave("0");
  	}
  
  	/* whomp out the history line */
  	(void) fputs(msgid, stdout);
! 	printf("\t%ld~", (long)datercv);
  	(void) fputs(expiry, stdout);
  	(void) putchar('\t');
  	(void) fputs(name, stdout);
  	(void) putchar('\n');
  	(void) fflush(stdout);
+ 	free(msgid);
+ 	free(expiry);
  }
  
  /*

*** cnpatch/tmp.file	Thu Aug 24 15:39:39 1989
--- expire/histslash.c	Wed Aug 23 16:39:28 1989
***************
*** 4,22 ****
   */
  #include <stdio.h>
  #include <assert.h>
  
  char *progname = "histslash";
  
- char buf[4096];			/* paranoia -- ought to be lots */
- 
  main()
  {
  	register char *scan;
  	register char *last;
  	extern char *strchr();
  
! 	while (fgets(buf, sizeof(buf), stdin) != NULL) {
! 		scan = strchr(buf, '\t');
  		scan = strchr(scan+1, '\t');
  		scan++;
  		last = NULL;
--- 4,22 ----
   */
  #include <stdio.h>
  #include <assert.h>
+ #include "fgetmfs.h"
  
  char *progname = "histslash";
  
  main()
  {
  	register char *scan;
  	register char *last;
+ 	register char *line;
  	extern char *strchr();
  
! 	while ((line = fgetms(stdin)) != NULL) {
! 		scan = strchr(line, '\t');
  		scan = strchr(scan+1, '\t');
  		scan++;
  		last = NULL;
***************
*** 31,36 ****
  			}
  			scan++;
  		}
! 		fputs(buf, stdout);
  	}
  }
--- 31,37 ----
  			}
  			scan++;
  		}
! 		fputs(line, stdout);
! 		free(line);
  	}
  }

*** cnpatch/tmp.file	Thu Aug 24 15:39:40 1989
--- expire/mkdbm.c	Wed Aug 23 16:46:15 1989
***************
*** 7,16 ****
  #include <stdio.h>
  #include <string.h>
  #include <ctype.h>
  
- char buf[4096];			/* ought to be plenty */
  
- 
  char *progname = "mkdbm";
  typedef struct { char *dptr; int dsize; } datum;
  
--- 7,15 ----
  #include <stdio.h>
  #include <string.h>
  #include <ctype.h>
+ #include "fgetmfs.h"
  
  
  char *progname = "mkdbm";
  typedef struct { char *dptr; int dsize; } datum;
  
***************
*** 20,51 ****
  	long place;
  	datum lhs;
  	datum rhs;
! 	register int ret;
  
! 	close(creat("hist.dir", 0666));
! 	close(creat("hist.pag", 0666));
  	if (dbminit("hist") < 0)
  		error("unable to do dbminit(\"hist\")", "");
  
  	for (;;) {
  		place = ftell(stdin);
! 		if (fgets(buf, sizeof(buf), stdin) == NULL)
  			break;
  
! 		scan = strchr(buf, '\t');
! 		if (scan == NULL || buf[strlen(buf)-1] != '\n') {
! 			fprintf(stderr, "bad format: %s", buf);
  			exit(1);
  		}
  		*scan = '\0';
  
! 		lhs.dptr = buf;
! 		lhs.dsize = strlen(buf) + 1;
  		rhs.dptr = (char *)&place;
  		rhs.dsize = sizeof place;
! 		ret = store(lhs, rhs);
! 		if (ret < 0)
! 			fprintf(stderr, "dbm failure '%s' @ %ld\n", buf, place);
  	}
  	exit(0);
  }
--- 19,51 ----
  	long place;
  	datum lhs;
  	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;
  
! 		scan = strchr(line, '\t');
! 		if (scan == NULL || line[strlen(line)-1] != '\n') {
! 			fprintf(stderr, "bad format: `%.60s'\n", line);
  			exit(1);
  		}
  		*scan = '\0';
  
! 		lhs.dptr = line;
! 		lhs.dsize = strlen(line) + 1;
  		rhs.dptr = (char *)&place;
  		rhs.dsize = sizeof place;
! 		if (store(lhs, rhs) < 0)
! 			fprintf(stderr, "dbm failure `%.50s' @ %ld\n", line, place);
! 		free(line);
  	}
  	exit(0);
  }

*** cnpatch/tmp.file	Thu Aug 24 15:39:42 1989
--- expire/superkludge	Wed Aug 23 16:31:57 1989
***************
*** 27,34 ****
  	do
  		awk 'BEGIN { mid = "xxx" }
  			/^$/ { exit }	# goes to END
! 			/^Supersedes:[ 	]/ { sup = $2 }
! 			/^Message-ID:[ 	]/ { mid = $2 }
  			END { print FILENAME, mid, sup ; exit }' $f >>/tmp/sup$$
  	done
  	awk 'NF > 3 || $2 !~ /^<.*>$/ || $3 !~ /^(<.*>)?$/' /tmp/sup$$ >/tmp/supx$$
--- 27,34 ----
  	do
  		awk 'BEGIN { mid = "xxx" }
  			/^$/ { exit }	# goes to END
! 			/^[Ss][Uu][Pp][Ee][Rr][Ss][Ee][Dd][Ee][Ss]:[ 	]/ { sup = $2 }
! 			/^[Mm][Ee][Ss][Ss][Aa][Gg][Ee]-[Ii][Dd]:[ 	]/ { mid = $2 }
  			END { print FILENAME, mid, sup ; exit }' $f >>/tmp/sup$$
  	done
  	awk 'NF > 3 || $2 !~ /^<.*>$/ || $3 !~ /^(<.*>)?$/' /tmp/sup$$ >/tmp/supx$$

*** cnpatch/tmp.file	Thu Aug 24 15:39:43 1989
--- expire/updatemin.c	Thu Aug 24 14:25:22 1989
***************
*** 61,66 ****
--- 61,68 ----
  	a = fopen("active", "r");
  	if (a == NULL)
  		fail("cannot open `%s'", ctlfile("active"));
+ 	if (fopen(newname, "r") != NULL)
+ 		fail("`%s' already exists", newname);
  	new = fopen(newname, "w");
  	if (new == NULL)
  		fail("cannot create `%s'", ctlfile(newname));
***************
*** 104,109 ****
--- 106,113 ----
  		else
  			fail("can't link in new `active' -- old one used", "");
  	}
+ 	if (unlink(newname) < 0)
+ 		fail("can't unlink `%s'", newname);
  	newsunlock();
  
  	exit(0);

*** cnpatch/tmp.file	Thu Aug 24 15:39:44 1989
--- h/Makefile	Wed Aug 23 15:40:46 1989
***************
*** 1,5 ****
  I = ../include
! INCLS = $(I)/alloc.h $(I)/config.h $(I)/fgetmfs.h $(I)/libc.h $(I)/news.h
  
  all:	$(INCLS)
  
--- 1,5 ----
  I = ../include
! INCLS = $(I)/alloc.h $(I)/config.h $(I)/fgetmfs.h $(I)/libc.h $(I)/news.h $(I)/case.h
  
  all:	$(INCLS)
  
***************
*** 11,16 ****
--- 11,18 ----
  	cp fgetmfs.h $@
  $(I)/libc.h:	libc.h
  	cp libc.h $@
+ $(I)/case.h:	case.h
+ 	cp case.h $@
  $(I)/news.h:	news.h newshsed
  	sed -f newshsed news.h >$@
  

*** cnpatch/tmp.file	Thu Aug 24 15:39:46 1989
--- h/libc.h	Tue Aug 22 17:18:32 1989
***************
*** 43,49 ****
  extern int strcmp(), strncmp(), strlen();	/* strings.h */
  #endif					/* A_STABLE_WORLD */
  extern char *strcpy(), *strcat(), *strncpy(), *strncat();	/* strings.h */
! extern char *index(), *rindex();	/* strings.h */
  extern char *memcpy();			/* memory.h */
  
  #ifdef A_STABLE_WORLD
--- 43,49 ----
  extern int strcmp(), strncmp(), strlen();	/* strings.h */
  #endif					/* A_STABLE_WORLD */
  extern char *strcpy(), *strcat(), *strncpy(), *strncat();	/* strings.h */
! extern char *strchr(), *strrchr();	/* strings.h */
  extern char *memcpy();			/* memory.h */
  
  #ifdef A_STABLE_WORLD

*** cnpatch/tmp.file	Thu Aug 24 15:39:46 1989
--- h/news.h	Thu Aug 24 14:57:07 1989
***************
*** 32,38 ****
  
  /* fundamental constants of the implementation */
  #define SMALLMEM	/* qqq for PDP-11s, PDP-8s, IBM PCs, etc. */
! #define	FASTINDEX	/* qqq if string functions are very fast */
  
  /* automatic configuration */
  #ifdef pdp11
--- 32,38 ----
  
  /* fundamental constants of the implementation */
  #define SMALLMEM	/* qqq for PDP-11s, PDP-8s, IBM PCs, etc. */
! #define	FASTSTRCHR	/* qqq if string functions are very fast */
  
  /* automatic configuration */
  #ifdef pdp11
***************
*** 71,81 ****
  /* STREQN is an optimised strncmp(a,b,n)==0; assumes n > 0 */
  #define STREQN(a, b, n) ((a)[0] == (b)[0] && strncmp(a, b, n) == 0)
  #define STRLEN(s) (sizeof (s) - 1)	/* s must be a char array */
! #ifdef FASTINDEX
! #define INDEX(src, chr, dest) (dest) = index(src, chr)
! extern char *index();
  #else
! #define INDEX(src, chr, dest) \
  	for ((dest) = (src); *(dest) != '\0' && *(dest) != (chr); ++(dest)) \
  		; \
  	if (*(dest) == '\0') \
--- 71,81 ----
  /* STREQN is an optimised strncmp(a,b,n)==0; assumes n > 0 */
  #define STREQN(a, b, n) ((a)[0] == (b)[0] && strncmp(a, b, n) == 0)
  #define STRLEN(s) (sizeof (s) - 1)	/* s must be a char array */
! #ifdef FASTSTRCHR
! #define STRCHR(src, chr, dest) (dest) = strchr(src, chr)
! extern char *strchr();
  #else
! #define STRCHR(src, chr, dest) \
  	for ((dest) = (src); *(dest) != '\0' && *(dest) != (chr); ++(dest)) \
  		; \
  	if (*(dest) == '\0') \

*** cnpatch/tmp.file	Thu Aug 24 15:39:49 1989
--- input/Makefile	Tue Aug 22 16:58:34 1989
***************
*** 9,15 ****
  COPTS = -O
  CFLAGS = $(COPTS) $(DEFINES) -I../include
  LINTFLAGS = $(DEFINES) -I../include -ha
- LDFLAGS = $(CFLAGS)
  LIBS= ../libcnews.a
  BATCH = ../batch
  THEMBIN = newsrun newsrunning c7decode bdecode recenews recpnews rnews
--- 9,14 ----
***************
*** 45,57 ****
  	: nothing
  
  newsspool: newsspool.o $(LIBS)
! 	$(CC) $(LDFLAGS) newsspool.o $(PRE) $(LIBS) $(POST) -o $@
  
  c7decode: c7decode.o $(LIBS)
! 	$(CC) $(LDFLAGS) c7decode.o $(PRE) $(LIBS) $(POST) -o $@
  
  bdecode: bdecode.o $(BATCH)/crctab.o $(LIBS)
! 	$(CC) $(LDFLAGS) bdecode.o $(BATCH)/crctab.o $(PRE) $(LIBS) $(POST) -o $@
  
  $(BATCH)/crctab.o:	$(BATCH)/crctab.c
  	( cd $(BATCH) ; make crctab.o )
--- 44,56 ----
  	: nothing
  
  newsspool: newsspool.o $(LIBS)
! 	$(CC) $(CFLAGS) $(LDFLAGS) newsspool.o $(PRE) $(LIBS) $(POST) -o $@
  
  c7decode: c7decode.o $(LIBS)
! 	$(CC) $(CFLAGS) $(LDFLAGS) c7decode.o $(PRE) $(LIBS) $(POST) -o $@
  
  bdecode: bdecode.o $(BATCH)/crctab.o $(LIBS)
! 	$(CC) $(CFLAGS) $(LDFLAGS) bdecode.o $(BATCH)/crctab.o $(PRE) $(LIBS) $(POST) -o $@
  
  $(BATCH)/crctab.o:	$(BATCH)/crctab.c
  	( cd $(BATCH) ; make crctab.o )

*** cnpatch/tmp.file	Thu Aug 24 15:39:51 1989
--- input/bdecode.c	Tue Aug 22 17:19:53 1989
***************
*** 17,23 ****
  	long nbytes2;
  	int w, crc2;
  	char buf[512];
! 	extern char *index();
  
  	myname = argv[0];
  	if (sizeof(word) < 4)
--- 17,23 ----
  	long nbytes2;
  	int w, crc2;
  	char buf[512];
! 	extern char *strchr();
  
  	myname = argv[0];
  	if (sizeof(word) < 4)
***************
*** 37,43 ****
  		if (fgets(buf, sizeof buf, fin) == NULL)
  			fatal("Missing header");
  		/* trim trailing blanks (sigh) */
! 		p = index(buf, '\n');
  		if (p == 0)
  			continue;
  		while (*--p == ' ')
--- 37,43 ----
  		if (fgets(buf, sizeof buf, fin) == NULL)
  			fatal("Missing header");
  		/* trim trailing blanks (sigh) */
! 		p = strchr(buf, '\n');
  		if (p == 0)
  			continue;
  		while (*--p == ' ')

*** cnpatch/tmp.file	Thu Aug 24 15:39:54 1989
--- libbig/active.fast.c	Tue Aug 22 17:20:53 1989
***************
*** 109,115 ****
  
  	if (i < nent)
  		*lnarrp++ = nlp;
! 	while (++i < nent && (nlp = index(nlp, '\n')) != NULL && *++nlp != '\0')
  		*lnarrp++ = nlp;
  	return i;		/* number of addrs stored */
  }
--- 109,115 ----
  
  	if (i < nent)
  		*lnarrp++ = nlp;
! 	while (++i < nent && (nlp = strchr(nlp, '\n')) != NULL && *++nlp != '\0')
  		*lnarrp++ = nlp;
  	return i;		/* number of addrs stored */
  }

*** cnpatch/tmp.file	Thu Aug 24 15:40:02 1989
--- libc/fgetmfs.c	Tue Aug 22 17:21:14 1989
***************
*** 110,116 ****
  	register char *nlp;
  
  	/* got a whole line: is it to be continued? */
! 	if (incr > 0 && cont && (nlp = rindex(line, '\n')) != NULL &&
  	    nlp > line && *--nlp == '\\') {
  		*nlp = '\0';			/* delete "\\\n" */
  		segment = nlp;
--- 110,116 ----
  	register char *nlp;
  
  	/* got a whole line: is it to be continued? */
! 	if (incr > 0 && cont && (nlp = strrchr(line, '\n')) != NULL &&
  	    nlp > line && *--nlp == '\\') {
  		*nlp = '\0';			/* delete "\\\n" */
  		segment = nlp;

*** cnpatch/tmp.file	Thu Aug 24 15:40:05 1989
--- libcnews/Makefile	Wed Aug 23 15:41:29 1989
***************
*** 10,18 ****
  #RANLIB=:
  SRCS=complain.c config.c fopenclex.c hostname.c \
   lock.c ltoza.c ngmatch.c readline.c \
!  string.c strlower.c strsave.c str3save.c time.c
  OBJS = complain.o config.o fopenclex.o gethdr.o hostname.o lock.o ltoza.o \
! 	nemalloc.o ngmatch.o str3save.o string.o strlower.o strsave.o time.o
  # workaround for System V make bug
  SHELL = /bin/sh
  
--- 10,19 ----
  #RANLIB=:
  SRCS=complain.c config.c fopenclex.c hostname.c \
   lock.c ltoza.c ngmatch.c readline.c \
!  string.c strlower.c strsave.c str3save.c time.c case.c
  OBJS = complain.o config.o fopenclex.o gethdr.o hostname.o lock.o ltoza.o \
! 	nemalloc.o ngmatch.o str3save.o string.o strlower.o strsave.o time.o \
! 	case.o
  # workaround for System V make bug
  SHELL = /bin/sh
  

*** cnpatch/tmp.file	Thu Aug 24 15:40:08 1989
--- libcnews/ngmatch.c	Tue Aug 22 17:29:16 1989
***************
*** 62,68 ****
  	for (ngp = ngs; ngp != NULL; ngp = ngcomma) {
  		register boolean match;
  
! 		INDEX(ngp, NGSEP, ngcomma);
  		if (ngcomma != NULL)
  			*ngcomma = '\0';	/* will be restored below */
  		match = mpatsmatch(rngpat, ngp); /* try 1 group, n-patterns */
--- 62,68 ----
  	for (ngp = ngs; ngp != NULL; ngp = ngcomma) {
  		register boolean match;
  
! 		STRCHR(ngp, NGSEP, ngcomma);
  		if (ngcomma != NULL)
  			*ngcomma = '\0';	/* will be restored below */
  		match = mpatsmatch(rngpat, ngp); /* try 1 group, n-patterns */
***************
*** 92,98 ****
  		(void) fprintf(stderr, "mpatsmatch(`%s', `%s')\n", ngpat, grp);
  	for (patp = ngpat; patp != NULL; patp = patcomma) {
  		negation = NO;
! 		INDEX(patp, NGSEP, patcomma);
  		if (patcomma != NULL)
  			*patcomma = '\0';	/* will be restored below */
  		if (*patp == NGNEG) {
--- 92,98 ----
  		(void) fprintf(stderr, "mpatsmatch(`%s', `%s')\n", ngpat, grp);
  	for (patp = ngpat; patp != NULL; patp = patcomma) {
  		negation = NO;
! 		STRCHR(patp, NGSEP, patcomma);
  		if (patcomma != NULL)
  			*patcomma = '\0';	/* will be restored below */
  		if (*patp == NGNEG) {
***************
*** 141,150 ****
  		register boolean match;
  
  	    	/* null-terminate words */
! 	    	INDEX(patwd, NGDELIM, patdot);
  		if (patdot != NULL)
  			*patdot = '\0';		/* will be restored below */
! 	    	INDEX(grwd, NGDELIM, grdot);
  		if (grdot != NULL)
  			*grdot = '\0';		/* will be restored below */
  
--- 141,150 ----
  		register boolean match;
  
  	    	/* null-terminate words */
! 	    	STRCHR(patwd, NGDELIM, patdot);
  		if (patdot != NULL)
  			*patdot = '\0';		/* will be restored below */
! 	    	STRCHR(grwd, NGDELIM, grdot);
  		if (grdot != NULL)
  			*grdot = '\0';		/* will be restored below */
  
***************
*** 197,203 ****
  {
  	register char *nextng;
  
! 	INDEX(ngs, NGSEP, nextng);
  	if (nextng == NULL)		/* no groups left */
  		return YES;
  	++nextng;			/* skip NGSEP */
--- 197,203 ----
  {
  	register char *nextng;
  
! 	STRCHR(ngs, NGSEP, nextng);
  	if (nextng == NULL)		/* no groups left */
  		return YES;
  	++nextng;			/* skip NGSEP */

*** cnpatch/tmp.file	Thu Aug 24 15:40:10 1989
--- libcnews/string.c	Tue Aug 22 17:29:39 1989
***************
*** 40,46 ****
  {
  	register char *nl;
  
! 	INDEX(s, '\n', nl);
  	if (nl != NULL)
  		*nl = '\0';
  }
--- 40,46 ----
  {
  	register char *nl;
  
! 	STRCHR(s, '\n', nl);
  	if (nl != NULL)
  		*nl = '\0';
  }
***************
*** 61,67 ****
  {
  	register char *endp, *copy;
  
! 	endp = index(s, c);		/* find interesting part's end of s */
  	if (endp != NULL)
  		*endp = '\0';		/* restored below */
  	copy = strsave(s);		/* copy interesting substring of s */
--- 61,67 ----
  {
  	register char *endp, *copy;
  
! 	endp = strchr(s, c);		/* find interesting part's end of s */
  	if (endp != NULL)
  		*endp = '\0';		/* restored below */
  	copy = strsave(s);		/* copy interesting substring of s */
***************
*** 78,84 ****
  	register int count = 0;
  
  #ifdef CLASSY
! 	for (; (s = index(s, c)) != NULL; s = (s == NULL? NULL: s+1))
  		++count;
  #else
  	while (*s != '\0')
--- 78,84 ----
  	register int count = 0;
  
  #ifdef CLASSY
! 	for (; (s = strchr(s, c)) != NULL; s = (s == NULL? NULL: s+1))
  		++count;
  #else
  	while (*s != '\0')
***************
*** 216,224 ****
  		*lastdelim = '\0';		/* omit user's name */
  
  	if (approved != NULL) {			/* moderated article */
! 		site = index(approved, '@');
  		if (site == NULL)
! 			site = index(nullify(sender), '@');
  	}
  	if (site != NULL) {
  		p = findhost(site+1, newpath);
--- 216,224 ----
  		*lastdelim = '\0';		/* omit user's name */
  
  	if (approved != NULL) {			/* moderated article */
! 		site = strchr(approved, '@');
  		if (site == NULL)
! 			site = strchr(nullify(sender), '@');
  	}
  	if (site != NULL) {
  		p = findhost(site+1, newpath);

*** cnpatch/tmp.file	Thu Aug 24 15:40:12 1989
--- libfake/Makefile	Wed Aug 23 15:49:49 1989
***************
*** 4,11 ****
  # workaround for System V make bug
  SHELL = /bin/sh
  
! ALL = dbm.o fsync.o getopt.o index.o ldiv.o memchr.o memcmp.o memcpy.o \
! memset.o mkdir.o putenv.o rindex.o strchr.o strcspn.o strpbrk.o strrchr.o \
  strspn.o strtok.o symlink.o
  
  # beware -- build knows about NEEDED
--- 4,11 ----
  # workaround for System V make bug
  SHELL = /bin/sh
  
! 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

*** cnpatch/tmp.file	Thu Aug 24 15:40:14 1989
--- libfake/getopt.c	Tue Aug 22 17:22:05 1989
***************
*** 9,15 ****
  
  static char	*scan = NULL;	/* Private scan pointer. */
  
! extern char	*index();
  
  int
  getopt(argc, argv, optstring)
--- 9,15 ----
  
  static char	*scan = NULL;	/* Private scan pointer. */
  
! extern char	*strchr();
  
  int
  getopt(argc, argv, optstring)
***************
*** 38,44 ****
  	}
  
  	c = *scan++;
! 	place = index(optstring, c);
  
  	if (place == NULL || c == ':') {
  		fprintf(stderr, "%s: unknown option -%c\n", argv[0], c);
--- 38,44 ----
  	}
  
  	c = *scan++;
! 	place = strchr(optstring, c);
  
  	if (place == NULL || c == ':') {
  		fprintf(stderr, "%s: unknown option -%c\n", argv[0], c);

*** cnpatch/tmp.file	Thu Aug 24 15:40:27 1989
--- libstdio/Makefile	Tue Aug 22 16:59:48 1989
***************
*** 31,40 ****
  
  stdiock.stock: stdiock.o $(LIBS)
  	: search -lc before libcnews.a to get stock stdio
! 	$(CC) $(CFLAGS) stdiock.o $(PRE) -lc $(LIBS) $(POST) -o $@
  stdiock.fast: stdiock.o $(OBJ) $(LIBS)
  	: load *.o by hand to get tuned stdio
! 	$(CC) $(CFLAGS) stdiock.o $(OBJ) $(PRE) $(LIBS) $(POST) -o $@
  
  clean:
  	rm -f *.o stdiock stdiock.fast stdiock.stock junk *mon.out
--- 31,40 ----
  
  stdiock.stock: stdiock.o $(LIBS)
  	: search -lc before libcnews.a to get stock stdio
! 	$(CC) $(CFLAGS) $(LDFLAGS) stdiock.o $(PRE) -lc $(LIBS) $(POST) -o $@
  stdiock.fast: stdiock.o $(OBJ) $(LIBS)
  	: load *.o by hand to get tuned stdio
! 	$(CC) $(CFLAGS) $(LDFLAGS) stdiock.o $(OBJ) $(PRE) $(LIBS) $(POST) -o $@
  
  clean:
  	rm -f *.o stdiock stdiock.fast stdiock.stock junk *mon.out

*** cnpatch/tmp.file	Thu Aug 24 15:40:39 1989
--- libv7/getcwd.c	Tue Aug 22 17:23:39 1989
***************
*** 6,12 ****
  
  /* imports from libc */
  extern FILE *popen();
! extern char *rindex();
  
  char *
  getcwd(path, size)
--- 6,12 ----
  
  /* imports from libc */
  extern FILE *popen();
! extern char *strrchr();
  
  char *
  getcwd(path, size)
***************
*** 23,29 ****
  		(void) pclose(fp);
  		return 0;
  	}
! 	if ((nlp = rindex(path, '\n')) != NULL)
  		*nlp = '\0';
  	(void) pclose(fp);
  	return path;
--- 23,29 ----
  		(void) pclose(fp);
  		return 0;
  	}
! 	if ((nlp = strrchr(path, '\n')) != NULL)
  		*nlp = '\0';
  	(void) pclose(fp);
  	return path;

*** cnpatch/tmp.file	Thu Aug 24 15:40:40 1989
--- libv7/gethostname.c	Tue Aug 22 17:23:17 1989
***************
*** 6,12 ****
  #include <stdio.h>
  
  /* imports from libc */
! extern char *index(), *strncpy();
  extern FILE *fopen(), *popen();
  
  /* forwards */
--- 6,12 ----
  #include <stdio.h>
  
  /* imports from libc */
! extern char *strchr(), *strncpy();
  extern FILE *fopen(), *popen();
  
  /* forwards */
***************
*** 61,67 ****
  
  		(void) fgets(hostname, size, whoami);
  		(void) pclose(whoami);
! 		if ((ptr = index(hostname, '\n')) != NULL)
  			*ptr = '\0';
  	}
  	if (*hostname != '\0')
--- 61,67 ----
  
  		(void) fgets(hostname, size, whoami);
  		(void) pclose(whoami);
! 		if ((ptr = strchr(hostname, '\n')) != NULL)
  			*ptr = '\0';
  	}
  	if (*hostname != '\0')
***************
*** 84,90 ****
  
  		(void) fgets(hostname, size, whoami);
  		(void) fclose(whoami);
! 		if ((ptr = index(hostname, '\n')) != NULL)
  			*ptr = '\0';
  	}
  }
--- 84,90 ----
  
  		(void) fgets(hostname, size, whoami);
  		(void) fclose(whoami);
! 		if ((ptr = strchr(hostname, '\n')) != NULL)
  			*ptr = '\0';
  	}
  }

*** cnpatch/tmp.file	Thu Aug 24 15:40:44 1989
--- man/expire.8	Wed Aug 23 15:52:01 1989
***************
*** 6,12 ****
  .ds c /usr/lib/news
  .\" =()<.ds m @<NEWSMASTER>@>()=
  .ds m usenet
! .TH EXPIRE 8 "5 June 1989" "C News"
  .SH NAME
  expire, doexpire \- expire old news
  .br
--- 6,12 ----
  .ds c /usr/lib/news
  .\" =()<.ds m @<NEWSMASTER>@>()=
  .ds m usenet
! .TH EXPIRE 8 "23 Aug 1989" "C News"
  .SH NAME
  expire, doexpire \- expire old news
  .br
***************
*** 40,45 ****
--- 40,47 ----
  .B \-v
  ] [
  .B \-d
+ ] [
+ .B \-r
  ]
  [ controlfile ]
  .br
***************
*** 69,75 ****
  operations are controlled by a control file
  (which can be named or supplied on standard input),
  which is not optional\(emthere is no default behavior.
! Each line of the control file should have four white-space-separated
  fields, as follows.
  .PP
  The first field is one or more newsgroups,
--- 71,79 ----
  operations are controlled by a control file
  (which can be named or supplied on standard input),
  which is not optional\(emthere is no default behavior.
! Each line of the control file
! (except for empty lines and lines starting with `#', which are ignored)
! should have four white-space-separated
  fields, as follows.
  .PP
  The first field is one or more newsgroups,
***************
*** 179,184 ****
--- 183,195 ----
  its line, to be expired only after all others have expired.
  (Meant for use on obnoxious systems like VMS which don't support real links.)
  .TP
+ .BR \-r
+ suppress \fIhistory\fR rebuild.
+ Mostly for emergencies.
+ (This leaves the \fIhistory\fR file out of date and larger than necessary,
+ but improves speed and eliminates the need for several megabytes of
+ temporary storage.)
+ .TP
  .BR \-v
  verbose:
  report some statistics after termination.
***************
*** 204,209 ****
--- 215,223 ----
  \fI\*c/explist\fR as the control file,
  and reports any difficulties by sending mail to \fI\*m\fR.
  This is usually better than just running \fIexpire\fR directly.
+ If space is adequate for archiving but persistently inadequate for the
+ temporaries needed for history rebuilding, \fIdoexpire\fR reports this
+ and invokes \fIexpire\fR with the \fB\-r\fR option.
  .PP
  .I Mkhistory
  rebuilds the \fIhistory\fR file and its auxiliaries to match the articles

*** cnpatch/tmp.file	Thu Aug 24 15:40:51 1989
--- misc/Makefile	Tue Aug 22 17:00:36 1989
***************
*** 34,49 ****
  	: nothing
  
  gngp:	gngp.o $(LIBS)
! 	$(CC) $(CFLAGS) gngp.o $(PRE) $(LIBS) $(POST) -o $@
  
  ctime:	ctime.o $(LIBS)
! 	$(CC) $(CFLAGS) ctime.o $(PRE) $(LIBS) $(POST) -o $@
  
  getdate:	getdate.o $(LIBS)
! 	$(CC) $(CFLAGS) getdate.o $(PRE) $(LIBS) $(POST) -o $@
  
  newslock:	newslock.o $(LIBS)
! 	$(CC) $(CFLAGS) newslock.o $(PRE) $(LIBS) $(POST) -o $@
  
  NHCFLAGS = -I$(RN) $(CFLAGS)
  RNEWSOBJS = $(RN)/history.o $(RN)/article.o $(RN)/hdrcommon.o \
--- 34,49 ----
  	: nothing
  
  gngp:	gngp.o $(LIBS)
! 	$(CC) $(CFLAGS) $(LDFLAGS) gngp.o $(PRE) $(LIBS) $(POST) -o $@
  
  ctime:	ctime.o $(LIBS)
! 	$(CC) $(CFLAGS) $(LDFLAGS) ctime.o $(PRE) $(LIBS) $(POST) -o $@
  
  getdate:	getdate.o $(LIBS)
! 	$(CC) $(CFLAGS) $(LDFLAGS) getdate.o $(PRE) $(LIBS) $(POST) -o $@
  
  newslock:	newslock.o $(LIBS)
! 	$(CC) $(CFLAGS) $(LDFLAGS) newslock.o $(PRE) $(LIBS) $(POST) -o $@
  
  NHCFLAGS = -I$(RN) $(CFLAGS)
  RNEWSOBJS = $(RN)/history.o $(RN)/article.o $(RN)/hdrcommon.o \
***************
*** 50,56 ****
   $(RN)/io.o $(RN)/msgs.o
  NHLIBS = $(LIBS) $(DBM)
  newshist:	newshist.o $(RNEWSOBJS) $(LIBS)
! 	$(CC) $(NHCFLAGS) newshist.o $(RNEWSOBJS) $(PRE) $(NHLIBS) $(POST) -o $@
  
  newshist.o:	newshist.c
  	$(CC) $(NHCFLAGS) -c newshist.c
--- 50,56 ----
   $(RN)/io.o $(RN)/msgs.o
  NHLIBS = $(LIBS) $(DBM)
  newshist:	newshist.o $(RNEWSOBJS) $(LIBS)
! 	$(CC) $(NHCFLAGS) $(LDFLAGS) newshist.o $(RNEWSOBJS) $(PRE) $(NHLIBS) $(POST) -o $@
  
  newshist.o:	newshist.c
  	$(CC) $(NHCFLAGS) -c newshist.c

*** cnpatch/tmp.file	Thu Aug 24 15:41:18 1989
--- relay/active.c	Tue Aug 22 17:23:57 1989
***************
*** 165,171 ****
  	register boolean result = NO;
  
  	for (ng = ngs; !result && ng != NULL; ng = newng) {
! 		newng = index(ng, NGSEP);
  		if (newng != NULL)
  			*newng = '\0';		/* restored below */
  
--- 165,171 ----
  	register boolean result = NO;
  
  	for (ng = ngs; !result && ng != NULL; ng = newng) {
! 		newng = strchr(ng, NGSEP);
  		if (newng != NULL)
  			*newng = '\0';		/* restored below */
  
***************
*** 187,193 ****
  	register int field;
  
  	for (field = 1; ngline != NULL && field < fieldno; ++field) {
! 		ngline = index(ngline, ' ');
  		if (ngline != NULL)
  			ngline++;		/* point at next field */
  	}
--- 187,193 ----
  	register int field;
  
  	for (field = 1; ngline != NULL && field < fieldno; ++field) {
! 		ngline = strchr(ngline, ' ');
  		if (ngline != NULL)
  			ngline++;		/* point at next field */
  	}

*** cnpatch/tmp.file	Thu Aug 24 15:41:36 1989
--- relay/control.c	Tue Aug 22 17:24:14 1989
***************
*** 109,115 ****
  		if (STREQN(s, "..", STRLEN("..")))
  			return NO;
  	for (s = SHELLMETAS; *s != '\0'; s++)
! 		if (index(cmd, *s) != NULL)
  			return NO;
  	return YES;
  }
--- 109,115 ----
  		if (STREQN(s, "..", STRLEN("..")))
  			return NO;
  	for (s = SHELLMETAS; *s != '\0'; s++)
! 		if (strchr(cmd, *s) != NULL)
  			return NO;
  	return YES;
  }

*** cnpatch/tmp.file	Thu Aug 24 15:41:40 1989
--- relay/fileart.c	Tue Aug 22 17:24:32 1989
***************
*** 103,109 ****
  		"%s: mklinks called with ST_REFUSED set (can't happen)\n",
  			progname);
  	for (; ngs != NULL; ngs = comma) {
! 		comma = index(ngs, NGSEP);
  		if (comma != NULL)
  			*comma = '\0';		/* will be restored below */
  		ng = realngname(ngs);
--- 103,109 ----
  		"%s: mklinks called with ST_REFUSED set (can't happen)\n",
  			progname);
  	for (; ngs != NULL; ngs = comma) {
! 		comma = strchr(ngs, NGSEP);
  		if (comma != NULL)
  			*comma = '\0';		/* will be restored below */
  		ng = realngname(ngs);

*** cnpatch/tmp.file	Thu Aug 24 15:41:42 1989
--- relay/hdrint.h	Tue Aug 22 16:34:22 1989
***************
*** 19,27 ****
  #ifndef DEFDIST
  #define DEFDIST "world"		/* default Distribution: */
  #endif
! #ifndef DEFMSGID
! #define DEFMSGID "<message-id@absent>"
! #endif
  
  #define JUNK "junk"
  #define ALL "all"
--- 19,25 ----
  #ifndef DEFDIST
  #define DEFDIST "world"		/* default Distribution: */
  #endif
! #define DEFMSGID ""		/* must be empty string or contain whitespace */
  
  #define JUNK "junk"
  #define ALL "all"

*** cnpatch/tmp.file	Thu Aug 24 15:41:43 1989
--- relay/hdrmunge.c	Tue Aug 22 17:24:57 1989
***************
*** 60,66 ****
  	if (!art->a_xref) {
  		art->a_xref = YES;
  		xrefs = strsave(art->a_files);
! 		for (slashp = xrefs; (slashp = index(slashp, FNDELIM)) != NULL; )
  			*slashp++ = ':';
  		if (fprintf(art->a_artf, "%s %s %s\n",
  		    xrefhdr.hdrnm, hostname(), xrefs) == EOF)
--- 60,66 ----
  	if (!art->a_xref) {
  		art->a_xref = YES;
  		xrefs = strsave(art->a_files);
! 		for (slashp = xrefs; (slashp = strchr(slashp, FNDELIM)) != NULL; )
  			*slashp++ = ':';
  		if (fprintf(art->a_artf, "%s %s %s\n",
  		    xrefhdr.hdrnm, hostname(), xrefs) == EOF)

*** cnpatch/tmp.file	Thu Aug 24 15:41:45 1989
--- relay/history.c	Tue Aug 22 17:25:14 1989
***************
*** 151,161 ****
  
  	trim(histent);
  	/* find start of 2nd field (arrival~expiry) */
! 	tabp = index(histent, FIELDSEP);
  	if (tabp == NULL)
  		return NULL;				/* mangled entry */
  	/* find start of 3rd field (files list) */
! 	else if ((tabp = index(tabp + 1, FIELDSEP)) == NULL)
  		return NULL;			/* cancelled or expired art. */
  	else
  		return tabp + 1;
--- 151,161 ----
  
  	trim(histent);
  	/* find start of 2nd field (arrival~expiry) */
! 	tabp = strchr(histent, FIELDSEP);
  	if (tabp == NULL)
  		return NULL;				/* mangled entry */
  	/* find start of 3rd field (files list) */
! 	else if ((tabp = strchr(tabp + 1, FIELDSEP)) == NULL)
  		return NULL;			/* cancelled or expired art. */
  	else
  		return tabp + 1;

*** cnpatch/tmp.file	Thu Aug 24 15:41:47 1989
--- relay/ihave.c	Tue Aug 22 17:25:31 1989
***************
*** 79,85 ****
  	argscp = strsave(argscp);
  
  	/* dig out the remote system name */
! 	remotesys = rindex(argscp, ' ');	
  	if (remotesys == NULL)			/* no msg-ids in command */
  		remotesys = argscp;
  	else {
--- 79,85 ----
  	argscp = strsave(argscp);
  
  	/* dig out the remote system name */
! 	remotesys = strrchr(argscp, ' ');	
  	if (remotesys == NULL)			/* no msg-ids in command */
  		remotesys = argscp;
  	else {
***************
*** 86,92 ****
  		remotesys = argscp + strlen(argscp) - 1;	/* last byte */
  		while (isascii(*remotesys) && isspace(*remotesys))
  			*remotesys-- = '\0';	/* back up to non-whitespace */
! 		remotesys = rindex(argscp, ' ');
  		if (remotesys == NULL)		/* no msg-ids in command */
  			remotesys = argscp;
  		else
--- 86,92 ----
  		remotesys = argscp + strlen(argscp) - 1;	/* last byte */
  		while (isascii(*remotesys) && isspace(*remotesys))
  			*remotesys-- = '\0';	/* back up to non-whitespace */
! 		remotesys = strrchr(argscp, ' ');
  		if (remotesys == NULL)		/* no msg-ids in command */
  			remotesys = argscp;
  		else

*** cnpatch/tmp.file	Thu Aug 24 15:41:50 1989
--- relay/makefile	Tue Aug 22 17:01:06 1989
***************
*** 54,60 ****
  	sed '/mkfile/d' makefile | mkconv | sed 's/make/mk/g' >$@
  
  relaynews: $(OBJ) $(LIBOBJS)
! 	$(CC) $(CFLAGS) $(OBJ) $(PRE) $(LIBS) $(LIBOBJS) $(POST) -o $@
  lint: $(SRC)
  	$(LINT) $(LINTFLAGS) $(SRC) $(LLIBS) | $(LINTFILT)
  lint-p: $(SRC)
--- 54,60 ----
  	sed '/mkfile/d' makefile | mkconv | sed 's/make/mk/g' >$@
  
  relaynews: $(OBJ) $(LIBOBJS)
! 	$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ) $(PRE) $(LIBS) $(LIBOBJS) $(POST) -o $@
  lint: $(SRC)
  	$(LINT) $(LINTFLAGS) $(SRC) $(LLIBS) | $(LINTFILT)
  lint-p: $(SRC)

*** cnpatch/tmp.file	Thu Aug 24 15:41:52 1989
--- relay/procart.c	Tue Aug 22 17:25:43 1989
***************
*** 296,301 ****
--- 296,308 ----
  	if (art->h.h_path == NULL) {
  		prefuse(art);
  		(void) printf("no Path: header\n");
+ 	} else if (art->h.h_msgid == NULL || art->h.h_msgid[0] == '\0') {
+ 		prefuse(art);
+ 		(void) printf("missing Message-ID\n");
+ 	} else if (strchr(art->h.h_msgid, ' ') != NULL ||
+ 	   strchr(art->h.h_msgid, '\t') != NULL) {
+ 		prefuse(art);
+ 		(void) printf("whitespace in Message-ID\n");
  	} else if (alreadyseen(art->h.h_msgid)) {
  		prefuse(art);
  		(void) printf("duplicate\n");
***************
*** 380,386 ****
  	/* this is a deadly tedious job and I really should automate it */
  	for (arts = filelist; arts != NULL && arts[0] != '\0';
  	     arts = (spacep == NULL? NULL: spacep+1)) {
! 		spacep = index(arts, ' ');
  		if (spacep != NULL)
  			spacep[0] = '\0';	/* will be restored below */
  		artnm = strsave(arts);
--- 387,393 ----
  	/* this is a deadly tedious job and I really should automate it */
  	for (arts = filelist; arts != NULL && arts[0] != '\0';
  	     arts = (spacep == NULL? NULL: spacep+1)) {
! 		spacep = strchr(arts, ' ');
  		if (spacep != NULL)
  			spacep[0] = '\0';	/* will be restored below */
  		artnm = strsave(arts);
***************
*** 387,393 ****
  		if (spacep != NULL)
  			spacep[0] = ' ';	/* restore space */
  
! 		slashp = index(artnm, FNDELIM);
  		if (slashp != NULL)
  			slashp[0] = '\0';	/* will be restored below */
  		if (artret)
--- 394,400 ----
  		if (spacep != NULL)
  			spacep[0] = ' ';	/* restore space */
  
! 		slashp = strchr(artnm, FNDELIM);
  		if (slashp != NULL)
  			slashp[0] = '\0';	/* will be restored below */
  		if (artret)

*** cnpatch/tmp.file	Thu Aug 24 15:42:22 1989
--- relay/sys.c	Tue Aug 22 17:29:50 1989
***************
*** 231,237 ****
  {
  	register char *colon;
  
! 	INDEX(line, ':', colon);
  	if (colon != NULL)
  		*colon++ = '\0';
  	return colon;
--- 231,237 ----
  {
  	register char *colon;
  
! 	STRCHR(line, ':', colon);
  	if (colon != NULL)
  		*colon++ = '\0';
  	return colon;
***************
*** 247,253 ****
  char *field;
  int delim;
  {
! 	register char *delimp = index(field, delim);
  
  	if (delimp != NULL)
  		*delimp++ = '\0';
--- 247,253 ----
  char *field;
  int delim;
  {
! 	register char *delimp = strchr(field, delim);
  
  	if (delimp != NULL)
  		*delimp++ = '\0';

*** cnpatch/tmp.file	Thu Aug 24 15:42:26 1989
--- relay/transmit.c	Tue Aug 22 17:24:44 1989
***************
*** 187,193 ****
  	(void) strcat(cmd, ";<");
  	(void) strcat(cmd, filename);
  	(void) strcat(cmd, " (");
! 	percent = index(syscmd, '%');
  	if (percent == NULL)
  		(void) strcat(cmd, syscmd);
  	else {
--- 187,193 ----
  	(void) strcat(cmd, ";<");
  	(void) strcat(cmd, filename);
  	(void) strcat(cmd, " (");
! 	percent = strchr(syscmd, '%');
  	if (percent == NULL)
  		(void) strcat(cmd, syscmd);
  	else {
***************
*** 194,200 ****
  		char *pcent2;
  
  		++percent;
! 		pcent2 = index(percent, '%');
  		if (pcent2 != NULL) {
  			art->a_status |= ST_DROPPED;
  			(void) fprintf(stderr, "%s: `%s' contains two %%'s\n",
--- 194,200 ----
  		char *pcent2;
  
  		++percent;
! 		pcent2 = strchr(percent, '%');
  		if (pcent2 != NULL) {
  			art->a_status |= ST_DROPPED;
  			(void) fprintf(stderr, "%s: `%s' contains two %%'s\n",

*** cnpatch/tmp.file	Thu Aug 24 15:42:43 1989
--- rna/makefile	Tue Aug 22 17:01:43 1989
***************
*** 44,50 ****
  	: warning, defs.h may not be right for your system
  
  readnews: $(ROFILES) defs.h $(LIBS)
! 	$(CC) $(CFLAGS) $(ROFILES) $(PRE) $(LIBS) $(POST) -o $@
  
  newsinstall:
  	: "install all control files; don't overwrite any!"
--- 44,50 ----
  	: warning, defs.h may not be right for your system
  
  readnews: $(ROFILES) defs.h $(LIBS)
! 	$(CC) $(CFLAGS) $(LDFLAGS) $(ROFILES) $(PRE) $(LIBS) $(POST) -o $@
  
  newsinstall:
  	: "install all control files; don't overwrite any!"

Files that are new:

new h/case.h (patch can't create, so diff against null):
Index: h/case.h
*** cnpatch/tmp.preposterously.long.name.to.make.patch.behave.right	Thu Aug 24 15:38:50 1989
--- h/case.h	Thu Aug 24 15:37:09 1989
***************
*** 0 ****
--- 1,5 ----
+ extern int cistrncmp();
+ 
+ /* must call the above once before invoking the macro below */
+ extern char casemap[];
+ #define	TOLOW(c)	(casemap[(c)])

new libcnews/case.c (patch can't create, so diff against null):
Index: libcnews/case.c
*** cnpatch/tmp.preposterously.long.name.to.make.patch.behave.right	Thu Aug 24 15:38:50 1989
--- libcnews/case.c	Thu Aug 24 15:37:42 1989
***************
*** 0 ****
--- 1,80 ----
+ /*
+  * case-mapping stuff
+  *
+  * We exploit the fact that we are dealing only with headers here, and
+  * 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>
+ #include "string.h"
+ #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? */
+ 
+ /*
+  - prime - set up case-mapping stuff
+  */
+ static void
+ prime()
+ {
+ 	register char *lp;
+ 	register char *up;
+ 	register int c;
+ 	static char lower[] = "abcdefghijklmnopqrstuvwxyz";
+ 	static char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ 
+ 	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;
+ }
+ 
+ /*
+  - cistrncmp - case-independent strncmp
+  */
+ int				/* < == > 0 */
+ cistrncmp(s1, s2, len)
+ char *s1;
+ char *s2;
+ int len;
+ {
+ 	register char *p1;
+ 	register char *p2;
+ 	register int n;
+ 
+ 	if (!primed)
+ 		prime();
+ 
+ 	p1 = s1;
+ 	p2 = s2;
+ 	n = len;
+ 	while (--n >= 0 && *p1 != '\0' && TOLOW(*p1) == TOLOW(*p2)) {
+ 		p1++;
+ 		p2++;
+ 	}
+ 	if (n < 0)
+ 		return(0);
+ 
+ 	/*
+ 	 * The following case analysis is necessary so that characters
+ 	 * which look negative collate low against normal characters but
+ 	 * high against the end-of-string NUL.
+ 	 */
+ 	if (*p1 == '\0' && *p2 == '\0')
+ 		return(0);
+ 	else if (*p1 == '\0')
+ 		return(-1);
+ 	else if (*p2 == '\0')
+ 		return(1);
+ 	else
+ 		return(TOLOW(*p1) - TOLOW(*p2));
+ }


end of patch 24-Aug-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