[comp.sources.unix] v19i097: Cnews production release, Patch1

rsalz@uunet.uu.net (Rich Salz) (06/30/89)

Submitted-by: utzoo!henry
Posting-number: Volume 19, Issue 97
Archive-name: cnews1/patch1


The following is the first formal, official patch to C News.  It includes
the two small ones that Geoff posted earlier; we apologize for the slightly
disorganized way that was done, but we were caught slightly unprepared.

It seems the copy of C News we sent to comp.sources.unix fell into a black
hole due to a mailer foulup.  It is being re-sent, including this patch.
Only people who picked up copies earlier, by FTP or UUCP, need this.
Existing FTPable copies will be updated as soon as possible; if there is
a PATCHDATES file immediately after the copyright notice, you've got a
current one.  The compressed current distribution is 387157 bytes.

This patch fixes a double handful of small bugs, one or two of them serious.
It also makes a few small improvements, including a considerable streamlining
of the processing in newsrun.  Finally, it includes a later version of the
fast-start modifications to rn.

Oh yes, and it also introduces a patch-tracking mechanism, date-based rather
than numeric but with the same sort of functionality.


start of patch 23-Jun-1989
this should be run with   patch -p0 <thisfile

The following are obsolete and should be deleted (there is no
easy way we can convince patch to do this automatically):
relay/TODO

Changed files, if any:

*** cnpatch/tmp.file	Fri Jun 23 14:34:49 1989
--- README	Thu Jun 22 14:11:05 1989
***************
*** 27,38 ****
  syndrome.)
  
  C News's files are fully compatible with those of B News for any program
! that does not inspect the middle field of the history file closely.  (The
! one major program that does is "nntp"; we include diffs for NNTP 1.5 which
! handle our middle-field format, interface it to our input subsystem, and
! generally make it quite a bit faster than the original.)  C News complies
! fully with RFC 1036 (nee RFC 850), the official definition of news interchange
! format.
  
  C News is, by intent and *we think* in practice, compatible with B News
  at the level of most interfaces to the normal user, which basically means
--- 27,38 ----
  syndrome.)
  
  C News's files are fully compatible with those of B News for any program
! that does not read log files and does not inspect the middle field of the
! history file closely.  (The one major program that does is "nntp"; we include
! diffs for NNTP 1.5 which handle our middle-field format, interface it to
! our input subsystem, and generally make it quite a bit faster than the
! original.)  C News complies fully with RFC 1036 (nee RFC 850), the official
! definition of news interchange format.
  
  C News is, by intent and *we think* in practice, compatible with B News
  at the level of most interfaces to the normal user, which basically means

*** cnpatch/tmp.file	Fri Jun 23 14:34:52 1989
--- batch/Makefile	Thu Jun 22 15:31:35 1989
***************
*** 83,92 ****
  	rm -rf bin
  	mkdir bin
  	echo 'ln $$* >/dev/null 2>/dev/null' >bin/newslock
! 	echo 'cat $*' >bin/munch
! 	echo '( echo --- ; cat $* ) >>output' >bin/xmit
! 	echo 'echo 2 ; cat $*' >bin/munch2
! 	echo '( echo +++ ; cat $* ) >>output' >bin/xmit2
  	echo 'echo 4' >bin/queuelen
  	echo 'echo 99' >bin/spacefor
  	ln batcher bin/batcher
--- 83,92 ----
  	rm -rf bin
  	mkdir bin
  	echo 'ln $$* >/dev/null 2>/dev/null' >bin/newslock
! 	echo 'cat' >bin/munch
! 	echo '( echo --- ; cat ) >>output' >bin/xmit
! 	echo 'echo 2 ; cat' >bin/munch2
! 	echo '( echo +++ ; cat ) >>output' >bin/xmit2
  	echo 'echo 4' >bin/queuelen
  	echo 'echo 99' >bin/spacefor
  	ln batcher bin/batcher

*** cnpatch/tmp.file	Fri Jun 23 14:35:02 1989
--- batch/viainews	Wed Jun 21 19:44:49 1989
***************
*** 1,4 ****
  #! /bin/sh
  # Feed batch to inews, for ihave/sendme mostly.
  
! exec inews -h
--- 1,4 ----
  #! /bin/sh
  # Feed batch to inews, for ihave/sendme mostly.
  
! exec inews -h -W

*** cnpatch/tmp.file	Fri Jun 23 14:35:06 1989
--- conf/Makefile	Thu Jun 22 16:12:47 1989
***************
*** 79,87 ****
  	rm -f log mailpaths sys cron rc setnewsids setnewsids.o spacefor.bsd
  	rm -f replyusepath spacefor queuelen junk
  
! gclean:
  	rm -f ../libcnews.a ../ranlibed
  	rm -rf ../include
  	for d in $(DIRS) ; do cd ../$$d ; make clean ; done
  
  spotless:	gclean
--- 79,89 ----
  	rm -f log mailpaths sys cron rc setnewsids setnewsids.o spacefor.bsd
  	rm -f replyusepath spacefor queuelen junk
  
! gclean:	tidy
  	rm -f ../libcnews.a ../ranlibed
  	rm -rf ../include
+ 
+ tidy:
  	for d in $(DIRS) ; do cd ../$$d ; make clean ; done
  
  spotless:	gclean

*** cnpatch/tmp.file	Fri Jun 23 14:35:12 1989
--- conf/build	Thu Jun 22 16:11:17 1989
***************
*** 346,356 ****
  	*)	fake="$fake $fn.o"	;;
  	esac
  done
! ./query "Does your system have a library function ldiv() as in ANSI C? [yes]? "
  read answer
  case "$answer" in
! y*|Y*|'')	;;
! *)	fake="$fake ldiv.o"	;;
  esac
  ./query 'Does your system have the "dbm" library [yes]? '
  read answer
--- 346,355 ----
  	*)	fake="$fake $fn.o"	;;
  	esac
  done
! ./query "Does your system have a library function ldiv() as in ANSI C? [no]? "
  read answer
  case "$answer" in
! n*|N*|'')	fake="$fake ldiv.o"	;;
  esac
  ./query 'Does your system have the "dbm" library [yes]? '
  read answer
***************
*** 364,369 ****
--- 363,371 ----
  		;;
  *)	fake="$fake dbm.o"
  	dbm='DBM='
+ 	echo "Okay, we'll fake it for you.  You might want to look at"
+ 	echo "contrib/dbz, which is a probably-superior fake that we have"
+ 	echo "not examined closely."
  	;;
  esac
  
***************
*** 409,415 ****
  	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 [yes]? '
  	read fastindex
  	case "$fastindex" in
  	y*|Y*|'')	fastindex=y	;;
--- 411,417 ----
  	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	;;
***************
*** 882,888 ****
  	echo "rm -f $ctlf"
  	echo "cp config.proto config"
  	echo "echo '$mailname' >mailname"
! 	echo "echo '$organization' >organization"
  	if test " $allowed" != " "
  	then
  		echo "echo '$allowed' >allowed"
--- 884,892 ----
  	echo "rm -f $ctlf"
  	echo "cp config.proto config"
  	echo "echo '$mailname' >mailname"
! 	echo "cat <<'!' >organization"
! 	echo "$organization"
! 	echo '!'
  	if test " $allowed" != " "
  	then
  		echo "echo '$allowed' >allowed"

*** cnpatch/tmp.file	Fri Jun 23 14:35:18 1989
--- conf/setnewsids.c	Thu Jun 22 14:32:47 1989
***************
*** 80,86 ****
  			newsgid = grp->gr_gid;
  		(void) endgrent();
  	}
! 	if (setgid(newsgid) < 0 || setuid(newsuid) < 0)
  		error("set[ug]id failed", "");
  	/* we are now running as news, so you can all relax */
  }
--- 80,87 ----
  			newsgid = grp->gr_gid;
  		(void) endgrent();
  	}
! 	if (setgid(newsgid) < 0 || setuid(newsuid) < 0 ||
! 	    getgid() != newsgid || getuid() != newsuid)	/* xenix workaround */
  		error("set[ug]id failed", "");
  	/* we are now running as news, so you can all relax */
  }

*** cnpatch/tmp.file	Fri Jun 23 14:35:22 1989
--- contrib/dbz	Fri Jun 23 13:11:14 1989
***************
*** 170,178 ****
  		lseek(Data_fd, data_ptr, 0);
  		read(Data_fd, buffer, (unsigned)key.dsize);
  
! 		/* key should be lcase version of article id and no tab */
  
! 		lcase(buffer, key.dsize);
  		if (buffer[key.dsize - 1] == '\t') {
  			buffer[key.dsize - 1] = '\0';
  		}
--- 170,178 ----
  		lseek(Data_fd, data_ptr, 0);
  		read(Data_fd, buffer, (unsigned)key.dsize);
  
! 		/* key should be article id and no tab */
  
! 		/* lcase(buffer, key.dsize);	lcase is a B news botch */
  		if (buffer[key.dsize - 1] == '\t') {
  			buffer[key.dsize - 1] = '\0';
  		}

*** cnpatch/tmp.file	Fri Jun 23 14:35:34 1989
--- contrib/rn.mod/README	Thu Jun 22 16:42:26 1989
***************
*** 31,34 ****
  group/1 will be around for a very long time, making rn spuriously think
  that the old groups are new.  Proper fixes for this problem involve
  reworking rn's strategy for determining new newsgroups completely,
! using the "active.times" file.  Volunteers?
--- 31,35 ----
  group/1 will be around for a very long time, making rn spuriously think
  that the old groups are new.  Proper fixes for this problem involve
  reworking rn's strategy for determining new newsgroups completely,
! using the "active.times" file.  The file "better.way" is an attempt
! to do exactly that.

*** cnpatch/tmp.file	Fri Jun 23 14:35:40 1989
--- doc/interface	Thu Jun 22 14:08:40 1989
***************
*** 183,188 ****
--- 183,192 ----
  Beware introducing major inefficiencies:
  \fIspacefor\fR is called a lot.
  (Our current one could stand to be faster, in fact.)
+ Beware, also, that \fIspacefor\fR is not intended to permit routine operation
+ using filesystems that are on the brink of being full;
+ the limits it imposes are only approximate, and no attempt has been made
+ to tune its clients to exploit every last available block.
  .PP
  \fIQueuelen\fR is invoked by the batcher to determine how long the current
  \fIuucp\fR queues are, so it can judge whether it should suspend batching

*** cnpatch/tmp.file	Fri Jun 23 14:35:46 1989
--- expire/dircheck	Thu Jun 22 15:23:30 1989
***************
*** 30,32 ****
--- 30,33 ----
  		fi
  	fi
  done
+ exit 0				# for stupid shells

*** cnpatch/tmp.file	Fri Jun 23 14:35:48 1989
--- expire/expire.c	Thu Jun 22 15:36:25 1989
***************
*** 102,108 ****
--- 102,112 ----
   * and also large enough for virtual certainty of getting the
   * Subject: line in the first bufferload.
   */
+ #ifdef SMALLMEM
+ char abuf[2*1024];		/* expire reported to be tight on 11 */
+ #else
  char abuf[8*1024];
+ #endif
  
  char *progname;
  

*** cnpatch/tmp.file	Fri Jun 23 14:35:59 1989
--- input/Makefile	Thu Jun 22 14:27:07 1989
***************
*** 29,34 ****
--- 29,35 ----
  bininstall:	all
  	chmod +x $(THEM) rnews
  	-if test ! -d $(NEWSBIN)/input ; then mkdir $(NEWSBIN)/input ; fi
+ 	rm -f $(NEWSBIN)/input/newsspool
  	cp $(THEM) $(NEWSBIN)/input
  	cp rnews $(RBIN)/rnews
  	cp rnews $(RBIN)/cunbatch
***************
*** 95,106 ****
  	rm -rf bin
  	mkdir bin
  	cp $(THEM) bin
  	rm -f tmp.1
  	here=`pwd` ; echo "cat >>$$here/tmp.1" >bin/relaynews
  	echo "echo 1" >bin/spacefor
  	echo 'ln $$*' >bin/newslock
  	echo 'echo 10' >bin/sizeof
! 	chmod +x bin/*
  	rm -rf in.coming
  	mkdir in.coming
  
--- 96,109 ----
  	rm -rf bin
  	mkdir bin
  	cp $(THEM) bin
+ 	mkdir bin/input
+ 	cp newsrun bin/input
  	rm -f tmp.1
  	here=`pwd` ; echo "cat >>$$here/tmp.1" >bin/relaynews
  	echo "echo 1" >bin/spacefor
  	echo 'ln $$*' >bin/newslock
  	echo 'echo 10' >bin/sizeof
! 	chmod +x bin/* bin/input/*
  	rm -rf in.coming
  	mkdir in.coming
  
***************
*** 125,131 ****
  	rm tmp.1
  	NEWSARTS=`pwd` NEWSCTL=`pwd` ./rnews.batch <test.1
  	NEWSARTS=`pwd` NEWSCTL=`pwd` ./rnews.batch <test.2
! 	NEWSARTS=`pwd` NEWSCTL=`pwd` ./rnews.immed <test.3
  	cmp tmp.1 test.out
  	test " `echo in.coming/*`" = ' in.coming/bad'
  	rm tmp.1
--- 128,134 ----
  	rm tmp.1
  	NEWSARTS=`pwd` NEWSCTL=`pwd` ./rnews.batch <test.1
  	NEWSARTS=`pwd` NEWSCTL=`pwd` ./rnews.batch <test.2
! 	NEWSARTS=`pwd` NEWSCTL=`pwd` NEWSBIN=`pwd`/bin ./rnews.immed <test.3
  	cmp tmp.1 test.out
  	test " `echo in.coming/*`" = ' in.coming/bad'
  	rm tmp.1

*** cnpatch/tmp.file	Fri Jun 23 14:36:01 1989
--- input/newsrun	Fri Jun 23 12:42:42 1989
***************
*** 28,95 ****
  	exit 0
  fi
  
- # Get rid of any old temporaries.
- rm -f nruntmp.*
- for f in `ls | egrep '^nspool'`
- do
- 	find $f -mtime +1 -exec rm -f '{}' ';'
- done
- 
  # Sort out where we are.
- me="`hostname`"
  if test -r $NEWSCTL/server
  then
  	server=`cat $NEWSCTL/server`
  else
  	server="$me"		# no server file --> we're it
  fi
  
  # Master loop.
! while true
  do
  	# Find some work.
! 	them=`ls | egrep '^[0-9]+$' | sort | sed 50q`
! 	if test "$them" = ""
  	then
! 		break
  	fi
  
  	# Do it.
  	for f in $them
  	do
  		# Check for request to stop.
  		if test -r stop
  		then
  			exit 0
  		fi
  
! 		# Check space.  It is *probably* better to stop processing
! 		# when things get too full.  (This test is actually a bit
! 		# inaccurate since the batch may be compressed, but it's
! 		# good enough to catch major space problems.)
! 		batchsize=`sizeof $f`
! 		if test " $batchsize" -eq 0		# empty batch
  		then
  			rm -f $f
! 			continue		# ugh
  		fi
! 		if test " `spacefor $batchsize articles`" -le 0
  		then
! 			exit 0
  		fi
  
! 		# Decompress if necessary.
  		text=nruntmp.$$
  		if compress -d <$f >$text 2>/dev/null
  		then
! 			rmlist="$f $text"
  		elif c7decode <$f 2>/dev/null | compress -d >$text 2>/dev/null
  		then
! 			rmlist="$f $text"
  		else
  			rm -f $text
  			text=$f
! 			rmlist="$f"
  		fi
  
  		# Do it.  -r redirects stdout and stderr into logs.  -n makes
--- 28,108 ----
  	exit 0
  fi
  
  # Sort out where we are.
  if test -r $NEWSCTL/server
  then
+ 	me="`hostname`"
  	server=`cat $NEWSCTL/server`
  else
+ 	me=me			# don't need actual name
  	server="$me"		# no server file --> we're it
  fi
  
  # Master loop.
! while :				# "while true", but : is faster
  do
  	# Find some work.
! 	them=`ls | sed '/[^0-9]/d;50q'`
! 	if test " $them" = " "
  	then
! 		break			# NOTE BREAK OUT
  	fi
  
+ 	# Check space.  It is *probably* better to stop processing
+ 	# when things get too full.  (This test is actually a bit
+ 	# inaccurate since the batches may be compressed, but it's
+ 	# good enough to catch major space problems.)
+ 	allsize=`sizeof $them`
+ 	if test " `spacefor $allsize articles`" -gt 1	# lots of room
+ 	then
+ 		muchroom=y
+ 	else
+ 		muchroom=
+ 	fi
+ 
  	# Do it.
+ 	rmlist=
  	for f in $them
  	do
  		# Check for request to stop.
  		if test -r stop
  		then
+ 			rm -f $rmlist
  			exit 0
  		fi
  
! 		# Check for empty.
! 		if test ! -s $f
  		then
  			rm -f $f
! 			continue			# NOTE CONTINUE
  		fi
! 
! 		# Space check, if we're close.
! 		if test " $muchroom" != " y"
  		then
! 			batchsize=`sizeof $f`
! 			if test " `spacefor $batchsize articles`" -le 0
! 			then
! 				rm -f $rmlist
! 				exit 0
! 			fi
  		fi
  
! 		# Decompress if necessary.  People who get lots of
! 		# uncompressed batches and never use c7 encoding might
! 		# want to remove the c7decode attempt to speed things up.
  		text=nruntmp.$$
  		if compress -d <$f >$text 2>/dev/null
  		then
! 			rmlist="$rmlist $f $text"
  		elif c7decode <$f 2>/dev/null | compress -d >$text 2>/dev/null
  		then
! 			rmlist="$rmlist $f $text"
  		else
  			rm -f $text
  			text=$f
! 			rmlist="$rmlist $f"
  		fi
  
  		# Do it.  -r redirects stdout and stderr into logs.  -n makes
***************
*** 128,137 ****
  							mail "$NEWSMASTER"
  		fi
  
- 		rm -f $rmlist
  	done
  done
- 
- find bad -mtime +7 -exec rm -f '{}' ';'
  
  exit 0
--- 141,148 ----
  							mail "$NEWSMASTER"
  		fi
  
  	done
+ 	rm -f $rmlist
  done
  
  exit 0

*** cnpatch/tmp.file	Fri Jun 23 14:36:03 1989
--- input/newsspool.c	Thu Jun 22 14:14:32 1989
***************
*** 105,111 ****
  			}
  
  	if (immed) {
! 		execlp("newsrun", "newsrun", (char *)NULL);
  		error("attempt to run newsrun failed!", "");
  	}
  	exit(0);
--- 105,112 ----
  			}
  
  	if (immed) {
! 		/* execlp because shell files may not be directly execable */
! 		execlp(binfile("input/newsrun"), "newsrun", (char *)NULL);
  		error("attempt to run newsrun failed!", "");
  	}
  	exit(0);

*** cnpatch/tmp.file	Fri Jun 23 14:36:19 1989
--- libcnews/string.c	Thu Jun 22 14:34:38 1989
***************
*** 166,172 ****
  	register int ch;
  
  	for (; *path != '\0'; path++)
! 		if (nothostchar(path[0], ch) && hostchar(path[1], ch))
  			++count;	/* trailing edge of delimiters */
  	return count;
  }
--- 166,173 ----
  	register int ch;
  
  	for (; *path != '\0'; path++)
! 		if (nothostchar(path[0], ch) &&
! 		    (hostchar(path[1], ch) || path[1] == '\0'))
  			++count;	/* trailing edge of delimiters */
  	return count;
  }
***************
*** 195,203 ****
  }
  
  /*
!  * Canonicalise rawpath: NULL -> "", chop last site (actually user name),
!  * and if approved:, chop everything after the site in approved (user@host):
!  * (or sender).
   * Result is malloced memory.
   */
  char *
--- 196,204 ----
  }
  
  /*
!  * Canonicalise rawpath: NULL -> "", chop last site (actually user name) but not
!  * its leading delimiter, and if Approved:, chop everything after the site,
!  * and its trailing delimiter, from Approved: (or Sender:) (user@host).
   * Result is malloced memory.
   */
  char *
***************
*** 205,216 ****
  char *rawpath, *approved, *sender;
  {
  	register char *newpath = strsave(nullify(rawpath));
! 	register char *p, *lastdelim = NULL, *site = NULL;
  	register int ch;
  
  	for (p = newpath; *p != '\0'; ++p)
  		if (nothostchar(*p, ch))
! 			lastdelim = p;
  	if (lastdelim != NULL)
  		*lastdelim = '\0';		/* omit user's name */
  
--- 206,217 ----
  char *rawpath, *approved, *sender;
  {
  	register char *newpath = strsave(nullify(rawpath));
! 	register char *p, *lastdelim = newpath, *site = NULL;
  	register int ch;
  
  	for (p = newpath; *p != '\0'; ++p)
  		if (nothostchar(*p, ch))
! 			lastdelim = p + 1;	/* just past delim */
  	if (lastdelim != NULL)
  		*lastdelim = '\0';		/* omit user's name */
  
***************
*** 221,227 ****
  	}
  	if (site != NULL) {
  		p = findhost(site+1, newpath);
! 		if (p != NULL)
  			*p = '\0';		/* terminate newpath after site */
  	}
  	return newpath;
--- 222,228 ----
  	}
  	if (site != NULL) {
  		p = findhost(site+1, newpath);
! 		if (p != NULL && *p++ != '\0')	/* delim after site? */
  			*p = '\0';		/* terminate newpath after site */
  	}
  	return newpath;

*** cnpatch/tmp.file	Fri Jun 23 14:36:44 1989
--- man/newsaux.8	Thu Jun 22 12:57:24 1989
***************
*** 6,12 ****
  .ds c /usr/lib/news
  .\" =()<.ds m @<NEWSMASTER>@>()=
  .ds m usenet
! .TH NEWSAUX 8 "9 June 1989" "C News"
  .SH NAME
  spacefor \- check available space for news
  .br
--- 6,12 ----
  .ds c /usr/lib/news
  .\" =()<.ds m @<NEWSMASTER>@>()=
  .ds m usenet
! .TH NEWSAUX 8 "22 June 1989" "C News"
  .SH NAME
  spacefor \- check available space for news
  .br
***************
*** 89,95 ****
  The precise locations of these places, and how low space gets before
  it is unduly cramped, are site-specific.
  .I Spacefor
! invokes \fIdu\fR(1) to determine the available space.
  .PP
  .I Queuelen
  reports how many news batches \fIuucp\fR has queued up for \fIsite\fR.
--- 89,95 ----
  The precise locations of these places, and how low space gets before
  it is unduly cramped, are site-specific.
  .I Spacefor
! invokes \fIdf\fR(1) to determine the available space.
  .PP
  .I Queuelen
  reports how many news batches \fIuucp\fR has queued up for \fIsite\fR.
***************
*** 212,218 ****
  .I Spacefor
  and
  .I queuelen
! are unfortunately somewhat system-specific, since \fIdu\fR output and
  \fIuucp\fR file layout vary between different versions.
  .PP
  The need for \fIsizeof\fR and \fInewslock\fR is a botch.
--- 212,218 ----
  .I Spacefor
  and
  .I queuelen
! are unfortunately somewhat system-specific, since \fIdf\fR output and
  \fIuucp\fR file layout vary between different versions.
  .PP
  The need for \fIsizeof\fR and \fInewslock\fR is a botch.

*** cnpatch/tmp.file	Fri Jun 23 14:36:46 1989
--- man/newsmail.8	Thu Jun 22 15:22:51 1989
***************
*** 6,16 ****
  .ds c /usr/lib/news
  .\" =()<.ds m @<NEWSMASTER>@>()=
  .ds m usenet
! .TH NEWSMAIL 8 "31 May 1989" "C News"
  .SH NAME
  mailnews, sendnews \- send unbatched news as mail
  .br
  recenews, recpnews \- receive mailed news
  .SH SYNOPSIS
  .B \*b/relay/mailnews
  address ...
--- 6,18 ----
  .ds c /usr/lib/news
  .\" =()<.ds m @<NEWSMASTER>@>()=
  .ds m usenet
! .TH NEWSMAIL 8 "22 June 1989" "C News"
  .SH NAME
  mailnews, sendnews \- send unbatched news as mail
  .br
  recenews, recpnews \- receive mailed news
+ .br
+ bdecode \- decode encoded mailed news
  .SH SYNOPSIS
  .B \*b/relay/mailnews
  address ...
***************
*** 21,26 ****
--- 23,31 ----
  .B \*b/input/recenews
  .br
  .B \*b/input/recpnews
+ .br
+ .B \*b/input/bdecode
+ [ file ]
  .SH DESCRIPTION
  Sometimes it is necessary to transmit news via mail,
  to deal with network connections that have no notion of arbitrary file
***************
*** 57,63 ****
--- 62,75 ----
  is sent to \fIrecenews\fR
  and likewise for ``rnews'' (the name is historical, for compatibility
  again) and \fIrecpnews\fR.
+ .PP
+ .I Bdecode
+ passes standard input, or the \fIfile\fR if there is one, to standard
+ output, decoding the \fIbencode\fR encoding and stripping off
+ debris prepended and appended by mailers.
  .SH SEE ALSO
  bencode(1), mail(1), news(5), newsbatch(8), rnews(8)
  .SH HISTORY
  Written at U of Toronto by Henry Spencer, with contributions by Geoff Collyer.
+ .I Bdecode
+ written at University of Waterloo by Reg Quinton and Ken Lalonde.

*** cnpatch/tmp.file	Fri Jun 23 14:36:50 1989
--- man/rnews.8	Thu Jun 22 15:20:42 1989
***************
*** 6,17 ****
  .ds c /usr/lib/news
  .\" =()<.ds m @<NEWSMASTER>@>()=
  .ds m usenet
! .TH RNEWS 8 "24 May 1989" "C News"
  .SH NAME
  rnews, cunbatch \- accept and spool news input
  .br
- recbnews, recpnews, bdecode \- accept and spool news received via mail
- .br
  newsspool, newsrun, c7decode \- news input spooler and processing
  .br
  newsrunning \- control news-processing daemon
--- 6,15 ----
  .ds c /usr/lib/news
  .\" =()<.ds m @<NEWSMASTER>@>()=
  .ds m usenet
! .TH RNEWS 8 "22 June 1989" "C News"
  .SH NAME
  rnews, cunbatch \- accept and spool news input
  .br
  newsspool, newsrun, c7decode \- news input spooler and processing
  .br
  newsrunning \- control news-processing daemon
***************
*** 22,32 ****
  .B cunbatch
  [ file ... ]
  .br
- .B \*b/input/recbnews
- .br
- .B \*b/input/recpnews
- .br
- .br
  .B \*b/input/newsspool
  [
  .B \-i
--- 20,25 ----
***************
*** 36,44 ****
  .br
  .B \*b/input/c7decode
  .br
- .B \*b/input/bdecode
- [ file ]
- .br
  .B \*b/input/newsrunning
  {\fBon\fR|\fBoff\fR}
  .SH DESCRIPTION
--- 29,34 ----
***************
*** 50,62 ****
  .IR rnews ;
  there is no difference in what they do.
  .PP
- .I Recbnews
- receives news sent as mail in
- \fIbencode\fR format (see \fInewsbatch\fR(8)),
- runs it through \fIbdecode\fR, and feeds it to \fIrnews\fR.
- .I Recpnews
- does likewise for news sent as mail with `N' prepended to each line.
- .PP
  .I Newsspool
  is the actual spooling program.
  It creates a spool file with a name based on the current time
--- 40,45 ----
***************
*** 99,108 ****
  .I C7decode
  passes standard input to standard output, decoding a complex and bizarre
  encoding of 8-bit data as printable ASCII characters.
- .I Bdecode
- passes standard input, or the \fIfile\fR if there is one, to standard
- output, decoding the \fIbencode\fR encoding and stripping off
- debris prepended and appended by mailers.
  .SH FILES
  .nf
  (All in \fI\*a/in.coming\fR)
--- 82,87 ----
***************
*** 115,120 ****
--- 94,100 ----
  .SH SEE ALSO
  compress(1),
  newsbatch(8),
+ newsmail(8),
  relaynews(8)
  .SH DIAGNOSTICS
  Complaints are mailed to \fB\*m\fR if something goes wrong.
***************
*** 124,130 ****
  .SH BUGS
  \fIC7decode\fR should be part of the underlying transport mechanism.
  It hasn't been tested very well in the C News environment.
! \fIBencode\fR is probably better.
! .PP
! \fIRecpnews\fR and the protocol it uses are obsolescent,
! as \fIrecbnews\fR and \fIbdecode\fR are far superior.
--- 104,107 ----
  .SH BUGS
  \fIC7decode\fR should be part of the underlying transport mechanism.
  It hasn't been tested very well in the C News environment.
! \fIBdecode\fR (see \fInewsmail\fR(8)) is probably better for most uses.

*** cnpatch/tmp.file	Fri Jun 23 14:36:52 1989
--- misc/addgroup	Thu Jun 22 15:06:04 1989
***************
*** 4,10 ****
  # =()<. ${NEWSCONFIG-@<NEWSCONFIG>@}>()=
  . ${NEWSCONFIG-/usr/lib/news/bin/config}
  
! PATH=$NEWSCTL/bin:$NEWSBIN/maint:$NEWSBIN:$NEWSPATH ; export PATH
  umask $NEWSUMASK
  
  usage="Usage: $0 groupname {y|n|m|x|=realgroup}"
--- 4,10 ----
  # =()<. ${NEWSCONFIG-@<NEWSCONFIG>@}>()=
  . ${NEWSCONFIG-/usr/lib/news/bin/config}
  
! PATH=$NEWSCTL/bin:$NEWSBIN/maint:$NEWSBIN/relay:$NEWSBIN:$NEWSPATH ; export PATH
  umask $NEWSUMASK
  
  usage="Usage: $0 groupname {y|n|m|x|=realgroup}"
***************
*** 48,50 ****
--- 48,55 ----
  done
  
  echo "$1 0000000000 0000000000 $2" >>$NEWSCTL/active
+ mkpdir $NEWSARTS/`echo $1 | tr . /`
+ 
+ SENDER=${USER-unknown}@`hostname`
+ echo "$1 `getdate now` $SENDER" >>$NEWSCTL/active.times  # rn hook
+ echo "newsgroup $1 was created locally by $SENDER." | mail $NEWSMASTER

*** cnpatch/tmp.file	Fri Jun 23 14:36:54 1989
--- misc/newsboot	Fri Jun 23 12:29:14 1989
***************
*** 10,19 ****
  cd $NEWSCTL
  rm -f L.* LOCK*				# leftover locks
  rm -f history.n*			# leftover expire work files
- rm -f $NEWSARTS/in.coming/nspool.*	# leftover input temporaries
  
- # nntp goo processing
  cd $NEWSARTS/in.coming
  for f in nntp.*				# find partial batches
  do
  	while test -f $f		# still there?
--- 10,18 ----
  cd $NEWSCTL
  rm -f L.* LOCK*				# leftover locks
  rm -f history.n*			# leftover expire work files
  
  cd $NEWSARTS/in.coming
+ rm -f nspool.* nruntmp.*		# leftover temporaries
  for f in nntp.*				# find partial batches
  do
  	while test -f $f		# still there?

*** cnpatch/tmp.file	Fri Jun 23 14:36:55 1989
--- misc/newsdaily	Fri Jun 23 12:29:41 1989
***************
*** 68,73 ****
--- 68,74 ----
  		echo
  	) >>$gripes
  fi
+ find bad -type f -mtime +7 -exec rm -f '{}' ';'
  
  # look for output anomalies
  cd $NEWSARTS/out.going

*** cnpatch/tmp.file	Fri Jun 23 14:37:07 1989
--- relay/README	Fri Jun 23 13:57:30 1989
***************
*** 17,20 ****
  wish to disable ihave/sendme (typically because of foolishness like
  proprietary newsgroups).
  
! To run a regression test, make relaynews, cd regress, and run "regress".
--- 17,20 ----
  wish to disable ihave/sendme (typically because of foolishness like
  proprietary newsgroups).
  
! To run a regression test, "make r".

*** cnpatch/tmp.file	Fri Jun 23 14:37:08 1989
--- relay/active.c	Mon Jun 12 04:46:50 1989
***************
*** 34,39 ****
--- 34,43 ----
  char actrelnm[] = "active";
  
  static FILE *actfp = NULL;
+ static struct lastngcache {
+ 	char *lnc_ng;			/* newsgroup name */
+ 	char *lnc_line;			/* matching active file line */
+ } lnc = { NULL, NULL };
  
  /*
   * return a pointer to the active file entry for ng
***************
*** 47,56 ****
  {
  	register char *ngline, *ng, *flag;
  	register int loopbreak = 100;
- 	static struct lastngcache {
- 		char *lnc_ng;		/* newsgroup name */
- 		char *lnc_line;		/* matching active file line */
- 	} lnc = { NULL, NULL };
  
  	if (lnc.lnc_ng != NULL && STREQ(lnc.lnc_ng, ang))
  		return lnc.lnc_line;
--- 51,56 ----
***************
*** 132,138 ****
  }
  
  /*
!  * Write back to disk the active file cache, if any.
   */
  statust
  actsync()
--- 132,139 ----
  }
  
  /*
!  * Write back to disk the active file cache, if any, and flush the
!  * last-newsgroup-cache, since it refers to the (now invalid) active file cache.
   */
  statust
  actsync()
***************
*** 140,145 ****
--- 141,147 ----
  	register statust status = ST_OKAY;
  
  	if (actfp != NULL) {
+ 		lnc.lnc_ng = lnc.lnc_line = NULL;
  		status |= actfsync(actfp);
  		if (nfclose(actfp) == EOF || status != ST_OKAY) {
  			warning("error writing `%s'", ctlfile(actrelnm));

*** cnpatch/tmp.file	Fri Jun 23 14:37:18 1989
--- relay/aux/mkpdir	Mon Jun 12 20:59:28 1989
***************
*** 4,10 ****
  # =()<. ${NEWSCONFIG-@<NEWSCONFIG>@}>()=
  . ${NEWSCONFIG-/usr/lib/news/bin/config}
  export NEWSCTL NEWSBIN NEWSARTS
! PATH=$NEWSCTL/bin:$NEWSBIN:$NEWSPATH ; export PATH	# must include this file's dir.
  
  umask $NEWSUMASK
  
--- 4,10 ----
  # =()<. ${NEWSCONFIG-@<NEWSCONFIG>@}>()=
  . ${NEWSCONFIG-/usr/lib/news/bin/config}
  export NEWSCTL NEWSBIN NEWSARTS
! PATH=$NEWSCTL/bin:$NEWSBIN/relay:$NEWSBIN:$NEWSPATH ; export PATH	# must include this file's dir.
  
  umask $NEWSUMASK
  

*** cnpatch/tmp.file	Fri Jun 23 14:37:22 1989
--- relay/control.c	Mon Jun 12 05:20:42 1989
***************
*** 170,177 ****
   * runctlmsg is called from a child of relaynews, so it must always
   * call _exit() rather than exit() to avoid flushing stdio buffers.
   *
!  * Enforce at least minimal security: standardise the environment,
!  * including PATH and IFS using standard(), a local addition to libc;
   * reject shell metacharacters in ctlcmd.
   */
  STATIC void
--- 170,177 ----
   * runctlmsg is called from a child of relaynews, so it must always
   * call _exit() rather than exit() to avoid flushing stdio buffers.
   *
!  * Enforce at least minimal security: the environment was standardised at
!  * startup, including PATH and IFS; close non-standard file descriptors;
   * reject shell metacharacters in ctlcmd.
   */
  STATIC void
***************
*** 181,187 ****
  	register char *cmd;
  	register int cmdstat;
  
! 	standard();				/* close most files, etc. */
  	if (!safecmd(ctlcmd)) {
  		(void) fprintf(stderr,
  		    "%s: control `%s' looks unsafe to execute\n", progname, ctlcmd);
--- 181,187 ----
  	register char *cmd;
  	register int cmdstat;
  
! 	closeall(1);
  	if (!safecmd(ctlcmd)) {
  		(void) fprintf(stderr,
  		    "%s: control `%s' looks unsafe to execute\n", progname, ctlcmd);

*** cnpatch/tmp.file	Fri Jun 23 14:37:23 1989
--- relay/ctl/checkgroups	Fri Jun 23 13:28:38 1989
***************
*** 35,43 ****
  	echo "The following newsgroups are not valid and should be removed."
  	sed "s/^/	/" /tmp/$$remove
  	echo ""
! 	echo "You can do this by executing the command:"
! 	echo "	$NEWSBIN/maint/rmgroup \\"
! 	sed 's;.*;		& \\;' /tmp/$$remove
  	echo ""
  fi 2>&1 >/tmp/$$out
  
--- 35,42 ----
  	echo "The following newsgroups are not valid and should be removed."
  	sed "s/^/	/" /tmp/$$remove
  	echo ""
! 	echo "You can do this by executing the commands:"
! 	sed "s;.*;	 $NEWSBIN/maint/delgroup &;" /tmp/$$remove
  	echo ""
  fi 2>&1 >/tmp/$$out
  

*** cnpatch/tmp.file	Fri Jun 23 14:37:24 1989
--- relay/ctl/newgroup	Fri Jun 23 13:31:33 1989
***************
*** 14,20 ****
  cat >$F
  
  # unapproved ctl msg? then quit
! grep -s '^Approved:' $F || { rm -f $F; exit 0; }
  
  SENDER="`grep '^Sender:' $F | sed 's/^[^:]*: *//'`"
  case "$SENDER" in
--- 14,20 ----
  cat >$F
  
  # unapproved ctl msg? then quit
! grep -s '^Approved:' $F >/dev/null || { rm -f $F; exit 0; }
  
  SENDER="`grep '^Sender:' $F | sed 's/^[^:]*: *//'`"
  case "$SENDER" in
***************
*** 22,28 ****
  esac
  
  greppat="^`echo $1 | sed 's/\./\\\\./g' ` "
! if grep -s "$greppat" $NEWSCTL/active; then	# group exists?
  	export SENDER
  	chamod "$1" "$2" 		# change moderated flag if needed
  	exit
--- 22,28 ----
  esac
  
  greppat="^`echo $1 | sed 's/\./\\\\./g' ` "
! if grep -s "$greppat" $NEWSCTL/active >/dev/null; then	# group exists?
  	export SENDER
  	chamod "$1" "$2" 		# change moderated flag if needed
  	exit

*** cnpatch/tmp.file	Fri Jun 23 14:37:31 1989
--- relay/makefile	Fri Jun 23 13:56:50 1989
***************
*** 67,72 ****
--- 67,73 ----
  install: $(NEWSBIN)/relay/relaynews
  $(NEWSBIN)/relay/relaynews: relaynews
  	-mkdir $(NEWSBIN)/relay $(NEWSBIN)/inject $(NEWSBIN)/ctl
+ 	rm -f $(NEWSBIN)/relay/relaynews
  	cp relaynews $(NEWSBIN)/relay
  	: needs to be news-owned, setuid -- build looks after that
  	chmod +x sh/* aux/* ctl/*
***************
*** 96,102 ****
  	(echo relaynews update of `date`; echo ""; bundle $?) | /bin/mail cnews-updates
  	touch $@
  clean:
! 	rm -f core a.out relaynews *.o
  	
  # header dependencies follow
  active.o: ../include/libc.h ../include/news.h ../include/config.h
--- 97,108 ----
  	(echo relaynews update of `date`; echo ""; bundle $?) | /bin/mail cnews-updates
  	touch $@
  clean:
! 	rm -f core a.out relaynews *.o	
! 	rm -rf regress/tmp
! 
! r:	relaynews
! 	chmod +x regress/regress
! 	cd regress; ./regress
  	
  # header dependencies follow
  active.o: ../include/libc.h ../include/news.h ../include/config.h

*** cnpatch/tmp.file	Fri Jun 23 14:37:45 1989
--- relay/relaynews.c	Thu Jun 22 14:32:32 1989
***************
*** 22,34 ****
   * testing is possible (and encouraged) in alternate directories.  This
   * does cause a loss of privilege, to avoid spoofing.
   *
!  * The disused old ihave/sendme protocol is dead; it's been broken in
!  * B news for ages but no one has noticed because it's essentially
!  * useless on the uucp network, especially when batching news articles.
!  * It is also only semi-documented, very wasteful and kludgey in the extreme.
!  * It is unreasonable to expect an ill-documented protocol to be implemented
!  * in new software, particularly one as kludgey as this one.
!  * The new ihave sys flag ("I") for NNTP is implemented (trivially).
   *
   * Portability vs SystemV.  relaynews uses dbm(3) and makes no apologies
   * for so doing.  Imitation UNIX (registered trademark of AT&T in the
--- 22,30 ----
   * testing is possible (and encouraged) in alternate directories.  This
   * does cause a loss of privilege, to avoid spoofing.
   *
!  * The disused old unbatched ihave/sendme protocol is gone because it was
!  * too wasteful; use the batched form instead (see the ihave sys flag
!  * ("I") instead).
   *
   * Portability vs SystemV.  relaynews uses dbm(3) and makes no apologies
   * for so doing.  Imitation UNIX (registered trademark of AT&T in the
***************
*** 175,180 ****
--- 171,179 ----
   * setuid()," and exec this program again.  If NEWSPERMS is set,
   * the failure is a fatal error (recursive loop).
   * This program (relaynews) can be setuid-news.
+  *
+  * The peculiar tests for failure (getuid() != newsuid) are to work
+  * around a Xenix bug which returns 0 from setuid() upon failure.
   */
  void
  setids(argv)
***************
*** 187,193 ****
  		newsuid = getuid(), newsgid = getgid();
  	else
  		newsuid = geteuid(), newsgid = getegid();
! 	if (setgid(newsgid) < 0 || setuid(newsuid) < 0) {
  		if (getenv("NEWSPERMS") != 0)
  			error("recursive loop setting ids", "");
  		execv(ctlfile(SETNEWSIDS), argv);
--- 186,193 ----
  		newsuid = getuid(), newsgid = getgid();
  	else
  		newsuid = geteuid(), newsgid = getegid();
! 	if (setgid(newsgid) < 0 || setuid(newsuid) < 0 ||
! 	    getgid() != newsgid || getuid() != newsuid) {
  		if (getenv("NEWSPERMS") != 0)
  			error("recursive loop setting ids", "");
  		execv(ctlfile(SETNEWSIDS), argv);

*** cnpatch/tmp.file	Fri Jun 23 14:37:47 1989
--- relay/sh/inews	Fri Jun 23 13:31:33 1989
***************
*** 204,210 ****
  
  # to post or to mail? that is the question; whether 'tis nobler in the mind
  # to suffer the slings and arrows of outrageous mailers - Bill Shakespeare
! if grep -s '^Control:' $inhdrs; then
  	echo "control"			# a dreadful hack around all.all.ctl
  else
  	sed -n '
--- 204,210 ----
  
  # to post or to mail? that is the question; whether 'tis nobler in the mind
  # to suffer the slings and arrows of outrageous mailers - Bill Shakespeare
! if grep -s '^Control:' $inhdrs >/dev/null; then
  	echo "control"			# a dreadful hack around all.all.ctl
  else
  	sed -n '
***************
*** 235,248 ****
  		>>$grpok
  		case "$flag" in
  		[nx])
! 			echo "$0: bugger off, $ng may not be posted to." >&2
  			echo 1 >$exitflag
  			trap 0		# this is a child process - no cleanup
  			exit 1		# dregs in /tmp/in$$*
  			;;
  		m)
! 			if grep -s '^Approved:[	 ]' $inhdrs; then
! 				rm $modroute		# just post normally
  			else
  				# un-Approved: mail it to the moderator(s).
  				echo "%s" >$modroute	# in case no route
--- 235,248 ----
  		>>$grpok
  		case "$flag" in
  		[nx])
! 			echo "$0: sorry, $ng may not be posted to locally." >&2
  			echo 1 >$exitflag
  			trap 0		# this is a child process - no cleanup
  			exit 1		# dregs in /tmp/in$$*
  			;;
  		m)
! 			if grep -s '^Approved:[	 ]' $inhdrs >/dev/null; then
! 				rm -f $modroute		# just post normally
  			else
  				# un-Approved: mail it to the moderator(s).
  				echo "%s" >$modroute	# in case no route

*** cnpatch/tmp.file	Fri Jun 23 14:37:49 1989
--- relay/sh/postnews	Thu Jun 22 14:02:03 1989
***************
*** 32,38 ****
  	ans=
  	while test " $ans" = " "
  	do
! 		echo -n "Newsgroup(s)$dprompt? "
  		read ans
  		case "$ans" in
  		'')	if test " $defg" != " "
--- 32,38 ----
  	ans=
  	while test " $ans" = " "
  	do
! 		echo "Newsgroup(s)$dprompt? " | tr -d '\012'
  		read ans
  		case "$ans" in
  		'')	if test " $defg" != " "
***************
*** 58,64 ****
  subj=
  while test " $subj" = " "
  do
! 	echo -n 'Subject: '
  	read subj
  done
  echo "Subject: $subj" >>$tmp
--- 58,64 ----
  subj=
  while test " $subj" = " "
  do
! 	echo 'Subject: ' | tr -d '\012'
  	read subj
  done
  echo "Subject: $subj" >>$tmp
***************
*** 82,88 ****
  while egrep '^(DELETE|REPLACE) THIS LINE' $tmp >/dev/null
  do
  	echo 'This posting does not appear to have been edited properly.'
! 	echo -n 'Abandon it [y] ? '
  	read ans
  	case "$ans" in
  	''|y*|Y*)
--- 82,88 ----
  while egrep '^(DELETE|REPLACE) THIS LINE' $tmp >/dev/null
  do
  	echo 'This posting does not appear to have been edited properly.'
! 	echo 'Abandon it [y] ? ' | tr -d '\012'
  	read ans
  	case "$ans" in
  	''|y*|Y*)

Files that are new:

new contrib/rn.mod/better.way (patch can't create, so diff against null):
Index: contrib/rn.mod/better.way
*** cnpatch/tmp.preposterously.long.name.to.make.patch.behave.right	Fri Jun 23 14:34:45 1989
--- contrib/rn.mod/better.way	Thu Jun 22 16:38:07 1989
***************
*** 0 ****
--- 1,465 ----
+ Date:  9 Jun 1989 1852-EDT (Friday)
+ From: csri.toronto.edu!moraes
+ Received: by neat.ai.toronto.edu id 11723; Fri, 9 Jun 89 18:52:43 EDT
+ Reply-To: moraes@csri.toronto.edu
+ X-Mailer: Mail User's Shell (6.3 6/25/88)
+ To:	henry@utzoo, geoff@utstat.toronto.edu
+ Subject: rn fixes
+ Cc:	moraes@csri.toronto.edu
+ Message-Id: <89Jun9.185243edt.11723@neat.ai.toronto.edu>
+ 
+ These are the rn fixes to make it use the new active.times file to
+ stop the startup problems when new newsgroups are created.
+ 
+ It seems fast, and reliable - also completely backward compatible, as
+ far as I can tell. Note that a new newsreader will now not be asked
+ about all the newsgroups - they can pick the ones they want later.
+ 
+ 	- moraes
+ 
+ # To unbundle, sh this file
+ echo README.rn 1>&2
+ sed 's/^-//' >README.rn <<'!'
+ The rn.mod file is a set of speedups for rn, which make use of a new file
+ which C news can generate, called $NEWSCTL/active.times. This file contains
+ the creation times of the newsgroups, and solves the problem of rn stat'ing
+ every newsgroup spool directory to figure out if it is a new newsgroup or
+ not.
+ 
+ The changes to addng.c prevent rn stating all ~700 directories under
+ -/usr/spool/news every time the active file changes (this is known as "the rn
+ huddle").  This reduced start up time after touching active from 108 seconds
+ elapsed on a Sun 3 to 5 seconds.
+ 
+ The theory behind the 700 stats in the newgroup huddle is apparently that if
+ rn stats group/1, and it exists, then group must be a newly-created group.
+ With rapid expiry, group/1 won't be around for long in most groups, causing
+ rn to miss some new groups, and in "valuable" groups with long expiry times,
+ group/1 will be around for a very long time, making rn spuriously think that
+ the old groups are new.
+ 
+ To get this to work - apply the diffs to rn. You may need some hand patching
+ -- our version of rn has been hacked to apply various local fixes and some U
+ of Waterloo fixes. (The base U of Waterloo rn contains two other handy
+ changes:  a -q which disables the interrogation when the active file
+ changes, and a third answer during the interrogation: "q" means "I don't
+ care, just show me some news, right now".)
+ 
+ The main changes are to addng.c, and init.c, to use the new procedure
+ checknewgroups() for detecting new groups, instead of the earlier heuristic.
+ 
+ Create a active.times file from your active file using the act.to.times
+ script in the C News distribution. (C News 'newgroup' will keep it uptodate)
+ 
+ Try it.
+ !
+ echo rn.mod 1>&2
+ sed 's/^-//' >rn.mod <<'!'
+ -*** /tmp/,RCSt1a11034	Fri Jun  9 18:36:21 1989
+ ---- addng.c	Fri Jun  9 18:33:55 1989
+ -***************
+ -*** 39,44 ****
+ ---- 39,50 ----
+ -  
+ -  #ifdef FINDNEWNG
+ -  /* generate a list of new newsgroups from active file */
+ -+ /*
+ -+  * The arguments are redundant - they used to be used in a heuristic to
+ -+  * determine new newsgroups. With C News active.times file, this is
+ -+  * unnecessary, since we use the faster, more reliable checknewgroups()
+ -+  * procedure.
+ -+  */
+ -  
+ -  bool
+ -  newlist(munged,checkinlist)
+ -***************
+ -*** 71,86 ****
+ -  		fprintf(tmpfp,"%s\n",buf);
+ -  					/* then remember said newsgroup */
+ -  	    }
+ -- #ifdef FASTNEW
+ -- 	    else {			/* not really a new group */
+ -- 		if (!munged) {		/* did we assume not munged? */
+ -- 		    fclose(tmpfp);	/* then go back, knowing that */
+ -- 		    UNLINK(tmpname);
+ -- 		    free(tmpname);
+ -- 		    return TRUE;	/* active file was indeed munged */
+ -- 		}
+ -- 	    }
+ -- #endif
+ -  	}
+ -  #ifdef DEBUGGING
+ -  	else
+ ---- 77,82 ----
+ -***************
+ -*** 106,127 ****
+ -      return FALSE;			/* do not call us again */
+ -  }
+ -  
+ -! /* return creation time of newsgroup */
+ -  
+ -  long
+ -  birthof(ngnam,ngsize)
+ -  char *ngnam;
+ -  ART_NUM ngsize;
+ -  {
+ --     long time();
+ -- 
+ --     /*
+ --      * This used to try and stat article 1 to find the newsgroup creating
+ --      * time. Almost never finds article 1, since it will always long gone.
+ --      * Nuke the stat() and speed up startup immensely.
+ --      */
+ --     /* not there, assume something good */
+ --     return (ngsize ? 0L : time(Null(long *)));
+ -  }
+ -  
+ -  bool
+ ---- 102,229 ----
+ -      return FALSE;			/* do not call us again */
+ -  }
+ -  
+ -! /*
+ -!  * gets the group time, from the second field, simultaneously null terminating
+ -!  * after the first field in buf.
+ -!  */
+ -! static long
+ -! getgrptime(buf)
+ -! char *buf;
+ -! {
+ -! 	char *s;
+ -! 	
+ -! 	s = index(buf, ' ');
+ -! 	if (s == Nullch || *(s+1) == '\0')
+ -! 		return 0L;
+ -! 	*s++ = '\0';
+ -! 	return(atol(s));
+ -! }
+ -  
+ -+ /*
+ -+  * Use the groups file (ACTIVE.times, typically /usr/lib/news/active.times) to
+ -+  * see if there are any new newsgroups
+ -+  */
+ -+ checknewgroups()
+ -+ {
+ -+     FILE *fp;
+ -+     long grptime;
+ -+     long ngrptime;
+ -+     long pos;
+ -+     long npos;
+ -+     char *s;
+ -+     char *grpfile;
+ -+     char tmpbuf[LBUFLEN];
+ -+ #define GROUPEXT ".times"
+ -+ 
+ -+     grpfile = safemalloc(strlen(filexp(ACTIVE)) + sizeof(GROUPEXT));
+ -+     strcpy(grpfile, filexp(ACTIVE));
+ -+     strcat(grpfile, GROUPEXT);
+ -+     
+ -+     fp = fopen(grpfile, "r");
+ -+     if (fp == (FILE *) NULL) {
+ -+ 	printf(cantopen, grpfile) FLUSH;
+ -+     	return;
+ -+     }
+ -+ 
+ -+     pos = npos = lastpos;
+ -+     grptime = lastgrptime;
+ -+     if (lastnewgroup != Nullch)
+ -+ 	strcpy(tmpbuf, lastnewgroup);
+ -+     /*
+ -+      * In the general case, this 'if()' will be false, unless someone has
+ -+      * messed up the groups file, or this is the first time this person is
+ -+      * reading news
+ -+      */
+ -+     if (lastnewgroup == Nullch || fseek(fp, lastpos, 0) == -1 ||
+ -+         fgets(buf, LBUFLEN, fp) == NULL ||
+ -+ 	!strnEQ(buf, lastnewgroup, strlen(lastnewgroup))) {
+ -+ 		/* We need to check the file from the start - use time */
+ -+ 		if (fseek(fp, 0L, 0) == -1) {
+ -+ 			printf(cantseek, grpfile) FLUSH;
+ -+ 			fclose(fp);
+ -+ 			free(grpfile);
+ -+ 			return;
+ -+ 		}
+ -+ 		pos = npos = 0L;
+ -+ 		while (fgets(buf, LBUFLEN, fp) != Nullch) {
+ -+ 			buf[strlen(buf)-1] = '\0';
+ -+ 			ngrptime = getgrptime(buf);
+ -+ 			if (ngrptime > lastgrptime)
+ -+ 				break;
+ -+ 			if (ngrptime == 0L)
+ -+ 				continue;
+ -+ 			grptime = ngrptime;
+ -+ 			strcpy(tmpbuf, buf);
+ -+ 			pos = npos;
+ -+ 			npos = ftell(fp);
+ -+ 		}
+ -+ 		if (fseek(fp, pos, 0) == -1) {
+ -+ 			printf(cantseek, grpfile) FLUSH;
+ -+ 			fclose(fp);
+ -+ 			free(grpfile);
+ -+ 			return;
+ -+ 		}
+ -+ 		npos = pos;
+ -+     }
+ -+     /*
+ -+      * At this point, the file pointer is positioned at the start of the first
+ -+      * new group. This is the value of pos. Now start asking about new groups.
+ -+      */
+ -+     while (fgets(buf, LBUFLEN, fp) != Nullch) {
+ -+ 	buf[strlen(buf)-1] = '\0';
+ -+ 	ngrptime = getgrptime(buf);
+ -+ 	if (ngrptime == 0L)
+ -+ 		continue;
+ -+ 	grptime = ngrptime;
+ -+ 	strcpy(tmpbuf, buf);
+ -+ 	pos = npos;
+ -+ 	if (grptime > lastgrptime && find_ng(buf) == nextrcline)
+ -+ 		/* not in .newsrc and newer that last new newsgroup */
+ -+ 		get_ng(buf, TRUE);
+ -+ 	npos = ftell(fp);
+ -+     }
+ -+     lastpos = pos;
+ -+     lastgrptime = grptime;
+ -+     if (lastnewgroup != Nullch)
+ -+     	free(lastnewgroup);
+ -+     lastnewgroup = savestr(tmpbuf);
+ -+     fclose(fp);
+ -+     free(grpfile);
+ -+ }
+ -+ 
+ -+ 	
+ -+ 
+ -+ /*
+ -+  * return creation time of newsgroup - procedure made redundant by C News
+ -+  * active.times and checknewgroups()
+ -+  */
+ -+ 
+ -+ /*ARGSUSED*/
+ -  long
+ -  birthof(ngnam,ngsize)
+ -  char *ngnam;
+ -  ART_NUM ngsize;
+ -  {
+ -  }
+ -  
+ -  bool
+ -*** /tmp/,RCSt1a11034	Fri Jun  9 18:36:24 1989
+ ---- common.h	Fri Jun  9 18:30:10 1989
+ -***************
+ -*** 1,9 ****
+ -! /* $Header: /ai/car/src/rn/RCS/common.h,v 4.6 89/06/09 18:29:44 moraes Exp $
+ -   * 
+ -   * $Log:	common.h,v $
+ --  * Revision 4.6  89/06/09  18:29:44  moraes
+ --  * *** empty log message ***
+ --  * 
+ -   * Revision 4.5  89/06/05  21:59:37  moraes
+ -   * enabled -q option permanantly. New speed mods make it unnecessary for
+ -   * most people, but some people just want to see general/gradnews/ut.*
+ ---- 1,6 ----
+ -! /* $Header: /ai/car/src/rn/RCS/common.h,v 4.5 89/06/05 21:59:37 moraes Exp $
+ -   * 
+ -   * $Log:	common.h,v $
+ -   * Revision 4.5  89/06/05  21:59:37  moraes
+ -   * enabled -q option permanantly. New speed mods make it unnecessary for
+ -   * most people, but some people just want to see general/gradnews/ut.*
+ -***************
+ -*** 292,299 ****
+ -  			/* (Note: both VERBOSE and TERSE can be defined; -t
+ -  			 * sets terse mode.  One or the other MUST be defined.
+ -  			 */
+ -- #define QUICK		/* -q option - Don't ask about new newsgroups */
+ -- 
+ -  #ifndef pdp11
+ -  #   define CACHESUBJ	/* cache subject lines in memory */
+ -  			/* without this ^N still works but runs really slow */
+ ---- 289,294 ----
+ -*** /tmp/,RCSt1a11034	Fri Jun  9 18:36:25 1989
+ ---- init.c	Fri Jun  9 18:30:10 1989
+ -***************
+ -*** 1,4 ****
+ -! /* $Header: /ai/car/src/rn/RCS/init.c,v 1.2 88/07/14 18:15:22 ken Exp $
+ -   *
+ -   * $Log:	init.c,v $
+ -   * Revision 1.2  88/07/14  18:15:22  ken
+ ---- 1,4 ----
+ -! /* $Header: init.c,v 1.2 88/07/14 18:15:22 ken Exp $
+ -   *
+ -   * $Log:	init.c,v $
+ -   * Revision 1.2  88/07/14  18:15:22  ken
+ -***************
+ -*** 166,185 ****
+ -  
+ -  #ifdef FINDNEWNG
+ -      fstat(actfp->_file,&filestat);	/* did active file grow? */
+ -- #ifdef QUICK
+ -      /* maintain the old active file size, to avoid "new newsgroup" blather */
+ -      if (quick)
+ -  	filestat.st_size = lastactsiz;
+ -- #endif
+ -      if (filestat.st_size != lastactsiz) {
+ -  	long actsiz = filestat.st_size;	/* remember new size */
+ -  	NG_NUM oldnext = nextrcline;	/* remember # lines in newsrc */
+ -- #ifdef FASTNEW
+ -- 	bool munged = writesoft || !lastactsiz;
+ -- 					/* bad soft ptrs -> edited active */
+ -- #else
+ -- 	bool munged = TRUE;		/* just assume .newsrc munged */
+ -- #endif
+ -  
+ -  #ifdef VERBOSE
+ -  	IF(verbose)
+ ---- 166,177 ----
+ -***************
+ -*** 190,208 ****
+ -  #ifdef TERSE
+ -  	    fputs("\nNew newsgroups:\n",stdout) FLUSH;
+ -  #endif
+ -! #ifdef FASTNEW
+ -! 	if (!munged) {			/* maybe just do tail of file? */
+ -! 	    fseek(actfp,lastactsiz-1,0);
+ -! 	    fgets(buf,LBUFLEN,actfp);
+ -! 	    munged = (*buf != '\n');
+ -! 	    if (!munged)
+ -! 		munged = newlist(munged,FALSE);
+ -! 	}
+ -! #endif
+ -! 	if (munged) {			/* must we scan entire file? */
+ -! 	    fseek(actfp,0L,0);		/* rewind active file */
+ -! 	    newlist(munged,FALSE);      /* sure hope they use hashing... */
+ -! 	}
+ -  	lastactsiz = actsiz;		/* remember for .rnlast */
+ -  	if (nextrcline != oldnext) {	/* did we add any new groups? */
+ -  	    foundany = TRUE;		/* let main() know */
+ ---- 182,188 ----
+ -  #ifdef TERSE
+ -  	    fputs("\nNew newsgroups:\n",stdout) FLUSH;
+ -  #endif
+ -! 	checknewgroups();
+ -  	lastactsiz = actsiz;		/* remember for .rnlast */
+ -  	if (nextrcline != oldnext) {	/* did we add any new groups? */
+ -  	    foundany = TRUE;		/* let main() know */
+ -*** /tmp/,RCSt1a11034	Fri Jun  9 18:36:26 1989
+ ---- last.c	Fri Jun  9 17:06:01 1989
+ -***************
+ -*** 1,9 ****
+ -! /* $Header: /ai/car/src/rn/RCS/last.c,v 1.1 89/06/09 03:52:49 moraes Exp $
+ -   *
+ -   * $Log:	last.c,v $
+ --  * Revision 1.1  89/06/09  03:52:49  moraes
+ --  * Initial revision
+ --  * 
+ -   * Revision 4.3  85/05/01  11:42:16  lwall
+ -   * Baseline for release with 4.3bsd.
+ -   * 
+ ---- 1,6 ----
+ -! /* $Header: last.c,v 4.3 85/05/01 11:42:16 lwall Exp $
+ -   *
+ -   * $Log:	last.c,v $
+ -   * Revision 4.3  85/05/01  11:42:16  lwall
+ -   * Baseline for release with 4.3bsd.
+ -   * 
+ -***************
+ -*** 26,37 ****
+ -      lastname = savestr(filexp(LASTNAME));
+ -      if ((tmpfp = fopen(lastname,"r")) != Nullfp) {
+ -  	fgets(tcbuf,1024,tmpfp);
+ -! 	tcbuf[strlen(tcbuf)-1] = '\0';
+ -  	lastngname = savestr(tcbuf);
+ -  	fgets(tcbuf,1024,tmpfp);
+ -  	lasttime = atol(tcbuf);
+ -  	fgets(tcbuf,1024,tmpfp);
+ -  	lastactsiz = atol(tcbuf);
+ -  	fclose(tmpfp);
+ -      }
+ -      else {
+ ---- 23,52 ----
+ -      lastname = savestr(filexp(LASTNAME));
+ -      if ((tmpfp = fopen(lastname,"r")) != Nullfp) {
+ -  	fgets(tcbuf,1024,tmpfp);
+ -! 	tcbuf[strlen(tcbuf) - 1] = '\0';
+ -  	lastngname = savestr(tcbuf);
+ -  	fgets(tcbuf,1024,tmpfp);
+ -  	lasttime = atol(tcbuf);
+ -  	fgets(tcbuf,1024,tmpfp);
+ -  	lastactsiz = atol(tcbuf);
+ -+ 	/*
+ -+ 	 * The first time when new rn is used by a user who was using the old
+ -+ 	 * rn, the lastgrptime is taken to be 'now', so the user is not
+ -+ 	 * hassled with hundreds of newsgroups
+ -+ 	 */
+ -+ 	if (fgets(tcbuf, 1024,tmpfp) != (char *) NULL)
+ -+ 		lastgrptime = atol(tcbuf);
+ -+ 	else 
+ -+ 		lastgrptime = time(0);
+ -+ 	if (fgets(tcbuf, 1024, tmpfp) != (char *) NULL) {
+ -+ 		tcbuf[strlen(tcbuf) - 1] = '\0';
+ -+ 		lastnewgroup = savestr(tcbuf);
+ -+ 	} else
+ -+ 		lastnewgroup = NULL;
+ -+ 	if (fgets(tcbuf, 1024, tmpfp) != (char *) NULL)
+ -+ 		lastpos = atol(tcbuf);
+ -+ 	else
+ -+ 		lastpos = 0;
+ -  	fclose(tmpfp);
+ -      }
+ -      else {
+ -***************
+ -*** 38,43 ****
+ ---- 53,67 ----
+ -  	lastngname = nullstr;
+ -  	lasttime = 0;
+ -  	lastactsiz = 0;
+ -+ 	/*
+ -+ 	 * The default for the new reader is not to show hundreds of new
+ -+ 	 * newsgroups. The system admin should use newsetup to provide a
+ -+ 	 * proper starting subset - the user can select new newsgroups by
+ -+ 	 * hand. Much faster
+ -+ 	 */
+ -+ 	lastgrptime = time(0);
+ -+ 	lastnewgroup = Nullch;
+ -+ 	lastpos = 0;
+ -      }
+ -  }
+ -  
+ -***************
+ -*** 47,54 ****
+ -  writelast()
+ -  {
+ -      if ((tmpfp = fopen(lastname,"w")) != Nullfp) {
+ -! 	fprintf(tmpfp,"%s\n%ld\n%ld\n",
+ -! 	    (ngname==Nullch?nullstr:ngname),(long)lasttime,(long)lastactsiz);
+ -  	fclose(tmpfp);
+ -      }
+ -      else
+ ---- 71,81 ----
+ -  writelast()
+ -  {
+ -      if ((tmpfp = fopen(lastname,"w")) != Nullfp) {
+ -! 	fprintf(tmpfp,"%s\n%ld\n%ld\n%ld\n%s\n%ld\n",
+ -! 	    (ngname==Nullch?nullstr:ngname),(long)lasttime,(long)lastactsiz,
+ -! 	    lastgrptime, 
+ -! 	    ((lastnewgroup == (char *) NULL) ? nullstr:lastnewgroup),
+ -! 	    lastpos);
+ -  	fclose(tmpfp);
+ -      }
+ -      else
+ -*** /tmp/,RCSt1a11034	Fri Jun  9 18:36:27 1989
+ ---- last.h	Fri Jun  9 05:32:16 1989
+ -***************
+ -*** 12,17 ****
+ ---- 12,20 ----
+ -  EXT char *lastngname INIT(Nullch);	/* last newsgroup read, from .rnlast file */
+ -  EXT long lasttime INIT(0);	/* time last rn was started up */
+ -  EXT long lastactsiz INIT(0);	/* size of active file when rn last started up */
+ -+ EXT long lastgrptime INIT(0);	/* time the groups file was last changed */
+ -+ EXT char *lastnewgroup INIT(Nullch);	/* last new newsgroup */
+ -+ EXT long lastpos INIT(0);	/* pos. of last new newsgroup in groups file */
+ -  
+ -  void	last_init();
+ -  void    writelast();
+ No differences encountered
+ !
+ 
+ 

Finally, update PATCHDATES:
*** ../cnpatch/tmp.dates	Fri Jun 23 14:38:03 1989
--- PATCHDATES	Fri Jun 23 14:38:03 1989
***************
*** 0 ****
--- 1 ----
+ 23-Jun-1989

end of patch 23-Jun-1989
-- 
NASA is to spaceflight as the  |     Henry Spencer at U of Toronto Zoology
US government is to freedom.   | uunet!attcan!utzoo!henry henry@zoo.toronto.edu


-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.