trn patch #1

Wayne Davison davison at drivax.UUCP
Tue Aug 21 13:48:38 AEST 1990


This is official patch #1 for trn v1.0.  It is a shar archive of the files
unipatch.c and patch1.  To extract it from trn type "e DIR" where DIR is
the directory of your trn source, or extract it will a de-shar'ing tool.
To apply the patch, compile the program unipatch.c with the command
"cc -o unipatch unipatch.c" and patch the source with the command
"unipatch <patch1 | patch".

** After patching, check Configure to ensure that WHITE and CTRLA (near the
top) have a Tab-Space and a Ctrl-A in them, respectively. **

This patch will generate trn v1.0.1, which has the following changes:

   o	Two structures in the thread database have been padded to provide
	a more portable database format.  The first time you run the new
	mthreads, it will detect the old database version number (in the
	db.init file), write a new db.init file, and re-generate all the
	thread files.  This will undoubtedly take more time than a regular
	update.

	If you are really adventurous (or KNOW that your machine is the
	kind that pads a 10-byte structure to be 12 bytes), you could
	remove the db.init file before running the new mthreads, and thus
	trick mthreads into skipping the database rebuild.  If you guess
	wrong, you'll need to manually remove all the thread files before
	running a "mthreads -f" to fix it.

   o	Mthreads' user interface has been significantly enhanced.  The
	command-line hierarchy has been modified to specify one or more
	groups to enable or disable thread processing for, which should
	eliminate the need for manual editing of the active2 file.  For
	example, running the command:

		mthreads comp,talk,!control

	would turn on processing for the comp and talk hierarchies, and
	turn off thread processing for control.  Mthreads automatically
	adds and removes thread files as needed.  New command-line options
	include:  -k (kill running mthreads process), -n (no thread process-
	ing, just turn groups on and off), -a automatically thread new groups,
	and -D debug mode.  See the new mthreads manpage for more details.

   o	Configure and mbox.saver.SH have been enhanced to deal with the
	MMDF mailbox format (message separator is ^A^A^A^A).  Pnews and
	Rnmail have been changed to use the mbox.saver instead of assuming
	unix-format messages.

   o	Configure does a better job of determining signal()'s return and
	tries harder to figure out if tzset() is available.

   o	Added a new Configuration option to read the site name from a file.
	This will aid sites that wish to use host hiding to route all their
	mail through one host address.

   o	Fixed a bug in the article opening routine when running trrn and
	attempting to open article #0 (an empty node).

   o	Changed mthreads to output '#' instead of '+' to avoid disconnecting
	Hayes-compatible modems.

   o	Fixed a problem in the handling of xrefs that point to groups that
	haven't yet been processed by mthreads.

   o	Fixed the backpager to backup over ^L's in articles.

   o	Reverted the default command for non-threaded groups to 'y' instead
	of '='.

   o	Added a warning message to trn when it can't find the db.init file.

   o	Added a check for interrupt in the new-newsgroup handling code
	that will allow you to break out of the prompts.

   o	Tweaked the byte-order determining code to work around dumb optimizers.

   o	Changed my address to our newly-registered domain.

Thanks for all the bug-reports/fixes/praise/etc!  I appreciate the input.
Enjoy!
-- 
 \  /| / /|\/ /| /(_)     Wayne Davison
(_)/ |/ /\|/ / |/  \      davison at dri.com	<<-- new domain name!
   (W   A  Y   N   e)     ...!uunet!drivax!davison

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	unipatch.c
#	patch1
# This archive created: Sun Aug 19 20:28:33 1990
# By:	Wayne Davison (Digital Research, Monterey CA)
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'unipatch.c'" '(1358 characters)'
if test -f 'unipatch.c'
then
	echo shar: "will not over-write existing file 'unipatch.c'"
else
cat << \SHAR_EOF > 'unipatch.c'
/*
A filter to turn a unidiff into a degenerate context diff (no '!'s)
for patch. Author: davison at dri.com (uunet!drivax!davison).
*/
#include <stdio.h>
#define ERR(a) {fputs(a,stderr);exit(1);}
struct Ln {
	struct Ln *lk;
	char t;
	char s[1];
} r,*h,*ln;
char *malloc();
main()
{
char bf[2048],*cp,ch;
long os,ol,ns,nl,ne,lncnt=0;
for(;;){
 for(;;){
	if(!fgets(bf,sizeof bf,stdin)) exit(0);
	lncnt++;
	if(!strncmp(bf,"@@ -",4)) break;
	fputs(bf,stdout);
 }
 if(sscanf(bf+4,"%ld,%ld +%ld,%ld %c",&os,&ol,&ns,&nl,&ch)!=5||ch!='@')
	goto bad;
 r.lk=0, h= &r, ne=ns+nl-1;
 printf("***************\n*** %ld,%ld ****\n",os,os+ol-(os>0));
 while(ol||nl){
	if(!fgets(bf,sizeof bf,stdin)){
		if(nl>2) ERR("Unexpected end of file.\n");
		strcpy(bf," \n");
	}
	lncnt++;
	if(*bf=='\t'||*bf=='\n')
		ch=' ', cp=bf;
	else
		ch= *bf, cp=bf+1;
	switch(ch){
	case'-':if(!ol--) goto bad;
		printf("- %s",cp);
		break;
	case'=':ch=' ';
	case' ':if(!ol--) goto bad;
		printf("  %s",cp);
	case'+':if(!nl--) goto bad;
		ln = (struct Ln*)malloc(sizeof(*ln)+strlen(cp));
		if(!ln) ERR("Out of memory!\n");
		ln->lk=0, ln->t=ch, strcpy(ln->s,cp);
		h->lk=ln, h=ln;
		break;
	default:
	bad:	fprintf(stderr,"Malformed unidiff at line %ld: ",lncnt);
		ERR(bf);
	}
 }
 printf("--- %ld,%ld ----\n",ns,ne);
 for(ln=r.lk;ln;ln=h){
	printf("%c %s",ln->t,ln->s);
	h=ln->lk;
	free(ln);
 }
}
}
SHAR_EOF
fi
echo shar: "extracting 'patch1'" '(57455 characters)'
if test -f 'patch1'
then
	echo shar: "will not over-write existing file 'patch1'"
else
cat << \SHAR_EOF > 'patch1'
Index: patchlevel
Prereq: v1.0
@@ -1,1 +1,1 @@
-Trn v1.0
+Trn v1.0.1
Index: Configure
@@ -4,7 +4,10 @@
=# shell scripts, Configure will trim # comments from them for you.
=#
-# $Header: Configure,v 4.3.3.1 90/07/24 21:56:31 davison Trn $
+# $Header: Configure,v 4.3.3.2 90/08/20 16:09:59 davison Trn $
=#
=# $Log:	Configure,v $
+# Revision 4.3.3.2  90/08/20  16:09:59  davison
+# Added MMDF support, revised sitename/domain/signal/tzset/PATH.
+# 
=# Revision 4.3.3.1  90/07/24  21:56:31  davison
=# Initial Trn Release
@@ -115,4 +118,7 @@
=# Yes, you may rip this off to use in other distribution packages.
=
+WHITE='[	 ]'; : there should be a tab and a space between the brackets.
+CTRLA=''; : there should be a control-A between the single-quotes.
+
=n=''
=c=''
@@ -167,4 +173,5 @@
=Header=''
=sitename=''
+hostfile=''
=domain=''
=orgname=''
@@ -232,5 +239,5 @@
=
=: sanity checks
-PATH='.:/bin:/usr/bin:/usr/local/bin:/usr/ucb:/usr/local:/usr/lbin:/etc'
+PATH='.:/bin:/usr/bin:/usr/local/bin:/usr/ucb:/usr/local:/usr/lbin:/etc:/usr/bsd'
=export PATH || (echo "OOPS, this isn't sh.  Desperation time.  I will feed myself to sh."; sh $0; kill $$)
=
@@ -570,5 +577,4 @@
=	rrninclude="-DUSG -DLAI_TCP"
=	socketlib=-lsocket
-	sigret=void
=	rdchk=define
=	dirtype=dirent
@@ -858,4 +864,30 @@
=$eunicefix filexp
=
+: try to deal with domains
+$cat << 'EOH'
+
+Please enter your domain name.  This will be used in conjunction with the
+site name for return addresses on news articles and mail.  If you use the
+4.3ism of having your domain in your hostname, all the posting programs
+will figure this out on the fly, so don't worry.
+
+Examples of some valid domains:
+	berkeley.edu
+	nasa.gov
+Example of an invalid domain in common use:
+	uucp
+EOH
+
+case "$domain" in
+'') dflt="uucp";;
+*)  dflt="$domain" ;;
+esac
+$echo $n "Your domain: [$dflt] $c"
+. myread
+case "$ans" in
+'') domain="$dflt";;
+*)  domain="$ans" ;;
+esac
+
=: now get the site name
=$echo " "
@@ -903,59 +935,55 @@
=esac
=
-: verify guess
+: verify site name and allow them to override it
=if $test "$sitename" ; then
=    $echo 'Your site name appears to be "'$sitename'".'
-    $echo $n "Is this correct? [y] $c"
-    . myread
-    case $ans in
-      y*|'')  ;;
-      *)      sitename='' ;;
-    esac
+else
+    sitename='unknown'
=fi
+case "$hostfile" in
+/*) dflt="$hostfile" ;;
+*)   dflt="$sitename" ;;
+esac
+$cat <<'EOM'
=
-: bad guess or no guess
-while $test "X$sitename" = X ; do
-    $echo $n "Please type the (one word) name of your site: $c"
-    . myread
-    sitename="$ans"
-    case $hostcmd in
-    sed*)
-	$echo "(That doesn't agree with your whoami.h file, by the way.)"
-	;;
-    *)
-	$echo "(That doesn't agree with your $hostcmd command, by the way.)"
+In some cases it is not desirable to use the actual site name in your return
+addresses (if, for example, all mail gets routed first to one site).  In this
+case trn allows you to either hard-wire a site name or read the site name from
+a file.  To indicate a file, start the name with a slash (e.g. /etc/sitename).
+To use just your domain name, re-enter it here.  A period-less site name will
+automatically get your domain name added to it.
+
+EOM
+while $test $dflt ; do
+    $echo $n "What site name goes in return addresses? [$dflt] $c"
+    . myread 
+    case $ans in
+    '') ans=$dflt;;
+    esac
+    case $ans in
+    /*)
+	if $test -f $ans ; then
+	    hostfile="$ans"
+	    hostcmd="$cat $ans"
+	    sitename=`$hostcmd`
+	    $echo "Trn will read the site name from $ans:  $sitename."
+	    dflt=''
+	else
+	    $echo "Unable to locate $ans."
+	fi
+	;;
+    *)  hostfile=''
+	if $test "X$sitename" = "X$ans" ; then
+	    $echo "Using the site name derived by $hostcmd:  $sitename."
+	else
+	    hostcmd=''
+	    sitename="$ans"
+	    $echo "Using a hard-wired site name:  $sitename."
+	fi
+	dflt=''
=	;;
=    esac
-    hostcmd=''
=done
=
-: try to deal with domains
-$cat << 'EOH'
-
-Please enter your domain name.  This will be used in conjunction
-with the site name for return addresses on news articles and
-mail.  If you use the 4.3ism of having your domain in your
-hostname, all the posting programs will figure this out on the
-fly, so don't worry.
-
-Examples of some valid domains:
-
-	berkeley.edu
-	nasa.gov
-Example of an invalid domain in common use:
-	uucp
-EOH
-
-case "$domain" in
-'') dflt="uucp";;
-*)  dflt="$domain" ;;
-esac
-$echo $n "Your domain: [$dflt] $c"
-. myread
-case "$ans" in
-'') domain="$dflt";;
-*)  domain="$ans" ;;
-esac
-
=if $test $portable = "undef" ; then
=	case $sitename in
@@ -1121,18 +1149,21 @@
=    ;;
=esac
-maildir='blurfl/dyick'
-while $test ! -d "$maildir" ; do
-    case $maildir in
-      blurfl*) ;;
-      *) $echo "$maildir does not appear to exist." ;;
-    esac
-    $echo " "
-    $echo $n "Where is yet-to-be-read mail spooled? [$dflt] $c"
-    . myread
-    maildir=`filexp "$ans"`
-    case $maildir in
-      '') maildir=$dflt ;;
-    esac
-done
+case "$dflt" in
+*%L*) ;;
+*)    dflt="$dflt/%L"
+esac
+$cat <<'EOM'
+
+Trn needs to know where to find yet-to-be-read mail.  Sendmail sites
+use /usr/spool/mail/%L (where '%L' is the user's login name).  Some
+MMDF sites use /usa/%L/.mail instead.
+
+EOM
+$echo $n "Where is yet-to-be-read mail spooled? [$dflt] $c"
+. myread
+maildir="$ans"
+case $maildir in
+'') maildir=$dflt ;;
+esac
=
=: find out how to find out full name
@@ -1303,4 +1334,26 @@
=fi
=
+: check for tzset.
+$echo " "
+if $contains tzset libc.list >/dev/null 2>&1 ||
+   $contains mktime libc.list >/dev/null 2>&1 ||
+   $contains tzset /usr/include/time.h >/dev/null 2>&1 ; then
+    $echo "Your system appears to use tzset() rather than ftime()."
+    $echo $n "Is this correct? [y] $c"
+    . myread
+    case $ans in
+	n*|f*) tzset='undef' ;;
+	*)     tzset='define' ;;
+    esac
+else
+    $echo "Your system appears to use ftime() rather than tzset()."
+    $echo $n "Is this correct? [y] $c"
+    . myread
+    case $ans in
+	n*|f*) tzset='define' ;;
+	*)     tzset='undef' ;;
+    esac
+fi
+
=: determine how to determine when a file is a mailbox
=case "$mboxchar" in
@@ -1314,8 +1367,8 @@
=of the file in question.  On most systems the first line starts "From...",
=so the first character is F.  On other systems there are magic cookies like
-control codes between articles, so one of those would be first.  On your
-system, if a file is in mailbox format, what is the first character of
+control codes between articles, so one of those would be first.  For example,
+MMDF messages are seperated with lines of 4 control-A's.  On your system, if a
=EOM
-$echo $n "that file? [$dflt] $c"
+$echo $n "file is in mailbox format, what is the first character of that file? [$dflt] $c"
=. myread
=mboxchar="$ans"
@@ -1325,4 +1378,5 @@
=case $mboxchar in
='F') ;;
+"$CTRLA") ;;
=*)  cat <<'EOM'
=You will need to edit the shell script mbox.saver to properly append an
@@ -1513,14 +1567,4 @@
=fi
=
-: check for tzset.  ass_u_me others have ftime.
-if $contains tzset libc.list >/dev/null 2>&1 ||
-   $contains mktime libc.list >/dev/null 2>&1 ; then
-    $echo "tzset() found."
-    tzset='define'
-else
-    $echo "No tzset() found -- we'll use ftime() instead."
-    tzset='undef'
-fi
-
=: see if YP could be running here
=if $contains yp_master.o libc.list >/dev/null 2>&1 ; then
@@ -1543,19 +1587,14 @@
=if [ -f /usr/include/signal.h ]
=then
-	WHITE='[	 ]'; : between the brackets are a tab and a space.
-	if grep "$WHITE*void$WHITE*(\*signal())();" \
-					/usr/include/signal.h >/dev/null
-	then
-		sigret=void
-	fi
-fi
+	$cpp /usr/include/signal.h >sigtest
+else
=if [ -f /usr/include/sys/signal.h ]
=then
-	WHITE='[	 ]'; : between the brackets are a tab and a space.
-	if grep "$WHITE*void$WHITE*(\*signal())();" \
-					/usr/include/sys/signal.h >/dev/null
-	then
-		sigret=void
-	fi
+	$cpp /usr/include/sys/signal.h >sigtest
+fi
+fi
+if grep "$WHITE*void$WHITE*(\*signal())();" sigtest >/dev/null
+then
+	sigret=void
=fi
=$echo "signal() returns $sigret on this system"
@@ -1564,4 +1603,10 @@
=gethostname=undef
=phostname=undef
+if $test ! "X$hostfile" = X ; then
+    gethostname=define
+else
+if $test "X$hostcmd" = X ; then
+    : it is already compiled in
+else
=if $contains gethostname.o libc.list >/dev/null 2>&1 ; then
=    $echo "gethostname() found."
@@ -1627,4 +1672,6 @@
=    fi
=fi
+fi
+fi
=
=: see if we need -ljobs and if we have sigset, etc.
@@ -1710,4 +1757,5 @@
=	    ndirc='ndir.c'
=	    ndiro='ndir.o'
+	    dirtype=direct
=	fi
=    fi
@@ -2459,4 +2507,5 @@
=Header='$Header'
=sitename='$sitename'
+hostfile='$hostfile'
=domain='$domain'
=orgname='$orgname'
@@ -2517,4 +2566,5 @@
=NNTPSRC='$NNTPSRC'
=CONFIG=true
+CTRLA='$CTRLA'
=EOT
=
@@ -2551,4 +2601,8 @@
=*)	isrrn2='/*';;
=esac
+case "$hostfile" in
+'')	usehostfile='/*';;
+*)	usehostfile='';;
+esac
=$cat <<EOT >config.h
=/* config.h
@@ -2557,6 +2611,10 @@
= */
=
-/* name of the site.  May be overridden by gethostname, uname, etc. */
+/* name of the site.  May be overridden by HOSTFILE, gethostname, uname, etc. */
=#define SITENAME "$sitename"
+$usehostfile#define HOSTFILE "$hostfile"
+
+/* OURDOMAIN is added to the site name if no "." is in it. */
+#define OURDOMAIN "$domain"
=
=/* name of the organization, may be a file name */
@@ -2585,5 +2643,5 @@
=
=/* location of spooled mail */
-#define MAILFILE "$maildir/%L"
+#define MAILFILE "$maildir"
=
=/* default shell--ok to be a slow shell like csh */
Index: Pnews.SH
@@ -5,7 +5,10 @@
=$spitshell >Pnews <<!GROK!THIS!
=$startsh
-# $Header: Pnews.SH,v 4.3.3.1 90/07/24 22:01:25 davison Trn $
+# $Header: Pnews.SH,v 4.3.3.2 90/08/20 16:24:09 davison Trn $
=#
=# $Log:	Pnews.SH,v $
+# Revision 4.3.3.2  90/08/20  16:24:09  davison
+# Use mbox.saver for AUTHORCOPY.  Fixed sitename handling.
+# 
=# Revision 4.3.3.1  90/07/24  22:01:25  davison
=# Initial Trn Release
@@ -65,5 +68,8 @@
=define)
=# your site name
-sitename=\`$hostcmd\`
+case "$hostcmd" in
+'') sitename="$sitename" ;;
+*)  sitename=\`$hostcmd\` ;;
+esac
=case \$sitename in
=	*.*)
@@ -507,7 +513,11 @@
=	;;
=    rescue)
-	$cat $tmpart >> ${HOME-$LOGDIR}/dead.article
-	$echo "Article appended to ${HOME-$LOGDIR}/dead.article"
-	$echo "A copy may be temporarily found in $tmpart"
+	if $test -s $tmpart; then
+		$cat $tmpart >> ${HOME-$LOGDIR}/dead.article
+		$echo "Article appended to ${HOME-$LOGDIR}/dead.article"
+		$echo "A copy may be temporarily found in $tmpart"
+	else
+		$echo "Null article discarded."
+	fi
=	exit
=	;;
@@ -519,10 +529,7 @@
=	    set X ${USER-${LOGNAME-`who am i`}} unknown
=	    shift
-	    logname=$1
-	    if $echo "From $logname `date`" >> $AUTHORCOPY; then
-		$cat $tmpart >> $AUTHORCOPY
+	    $rnlib/mbox.saver $tmpart "." "." 0 0 Pnews $AUTHORCOPY "From $1 `date`"
+	    if $test $? -eq 0 ; then
=		$echo "Article appended to $AUTHORCOPY"
-		$echo "" >> $AUTHORCOPY
-		$echo "" >> $AUTHORCOPY
=	    else
=		$echo "Cannot append to $AUTHORCOPY"
Index: README
@@ -91,4 +91,7 @@
=    which will lower the amount of space required for thread files.
=
+    ** If you got trn in shar format, check Configure to ensure that WHITE
+    and CTRLA have a Tab-Space and a Ctrl-A in them, respectively. **
+
=1)  Run Configure.  This will figure out various things about your system.
=    Some things Configure will figure out for itself, other things it will
@@ -125,9 +128,9 @@
=    reasonable place.
=
-5)  Once trn is all compiled, you need to create some thread data to be able
-    to use all the new features.  If you like, you can start small with a
-    command like:  "mthreads rec.humor.funny" or "mthreads news".  You can
-    also choose to create any subset of the entire hierarchy by modifying
-    the active2 file in the trn library.  Read the mthreads manpage for
+5)  Once trn is compiled, you need to create some thread data to be
+    able to use all the new features.  If you like, you can start small
+    with a command like:  "mthreads rec.humor.funny", process a few more
+    groups with the command "mthreads news", and then turn them all on
+    with the command "mthreads all".  Read the mthreads manpage for
=    complete details.
=
@@ -152,6 +155,6 @@
=    it on a regular basis with the standard-output redirected to /dev/null.
=
-9)  IMPORTANT!  Help save the world!  Communicate any problems and
-    suggested patches to davison%drivax at uunet.uu.net so we can keep
+9)  IMPORTANT!  Help save the world!  Communicate any problems and suggested
+    patches to davison at dri.com (...!uunet!drivax!davison) so we can keep
=    everyone in sync.  If you have a problem, there's someone else
=    out there who either has had or will have the same problem.  Please
Index: Rnmail.SH
@@ -5,7 +5,10 @@
=$spitshell >Rnmail <<!GROK!THIS!
=$startsh
-# $Header: Rnmail.SH,v 4.3.3.1 90/07/24 22:02:49 davison Trn $
+# $Header: Rnmail.SH,v 4.3.3.2 90/08/20 16:22:29 davison Trn $
=# 
=# $Log:	Rnmail.SH,v $
+# Revision 4.3.3.2  90/08/20  16:22:29  davison
+# Use mbox.saver for MAILRECORD.  Fixed sitename handling.
+# 
=# Revision 4.3.3.1  90/07/24  22:02:49  davison
=# Initial Trn Release
@@ -44,5 +47,8 @@
=case $portable in
=define)
-	sitename=\`$hostcmd\`
+	case "$hostcmd" in
+	'') sitename="$sitename" ;;
+	*)  sitename=\`$hostcmd\` ;;
+	esac
=	case \$sitename in
=		*.*)
@@ -312,12 +318,7 @@
=	    ;;
=	*)
-	    (
-		set X ${USER-${LOGNAME-`who am i`}} unknown
-		shift
-		$echo "From $1 `date`"
-		$cat $tmpart
-		$echo ""
-		$echo ""
-	    ) >> $MAILRECORD
+	    set X ${USER-${LOGNAME-`who am i`}} unknown
+	    shift
+	    $rnlib/mbox.saver $tmpart "." "." 0 0 Pnews $MAILRECORD "From $1 `date`"
=	    if $test $? -eq 0 ; then
=		$echo "Message appended to $MAILRECORD"
Index: addng.c
@@ -1,5 +1,8 @@
-/* $Header: addng.c,v 4.3.3.1 90/06/20 22:35:43 davison Trn $
+/* $Header: addng.c,v 4.3.3.2 90/08/20 16:27:06 davison Trn $
= *
= * $Log:	addng.c,v $
+ * Revision 4.3.3.2  90/08/20  16:27:06  davison
+ * Allow breaking out of ng adding.  Don't add 'X'ed groups.
+ * 
= * Revision 4.3.3.1  90/06/20  22:35:43  davison
= * Initial Trn Release
@@ -43,4 +46,5 @@
=#include "server.h"
=#endif
+#include "final.h"
=#include "INTERN.h"
=#include "addng.h"
@@ -71,4 +75,9 @@
=    }
=    while (fgets(buf,LBUFLEN,actfp) != Nullch) {
+	/* Check if they want to break out of the new newsgroups search */
+	if (int_count) {
+	    int_count = 0;
+	    return FALSE;
+	}
=	if (s = index(buf,' ')) {
=	    status=s;
@@ -75,5 +84,10 @@
=	    while (isdigit(*status) || isspace(*status)) status++;
=	    *s++ = '\0';
+#ifdef USETHREADS
+	    if (strnEQ(buf,"to.",3) || *status == 'x' || *status == 'X'
+				    || *status == '=')
+#else
=	    if (strnEQ(buf,"to.",3) || *status == 'x' || *status == '=')
+#endif
=	        /* since = groups are refiling to another group, just
=		   ignore their existence */
Index: art.c
@@ -1,5 +1,8 @@
-/* $Header: art.c,v 4.3.3.1 90/06/20 22:35:51 davison Trn $
+/* $Header: art.c,v 4.3.3.2 90/08/20 16:05:33 davison Trn $
= *
= * $Log:	art.c,v $
+ * Revision 4.3.3.2  90/08/20  16:05:33  davison
+ * Fixed bug in backpage code.
+ * 
= * Revision 4.3.3.1  90/06/20  22:35:51  davison
= * Initial Trn Release
@@ -824,6 +827,7 @@
=	target = topline - (LINES - 2);
=	artline = topline;
-	while (artline >= 0 && artline > target && vrdary(artline-1) >= 0)
+	if (artline >= 0) do {
=	    artline--;
+	} while(artline >= 0 && artline > target && vrdary(artline-1) >= 0);
=	topline = artline;
=			/* remember top line of screen */
Index: artio.c
@@ -1,5 +1,8 @@
-/* $Header: artio.c,v 4.3.3.1 90/07/21 20:11:03 davison Trn $
+/* $Header: artio.c,v 4.3.3.2 90/08/20 16:25:50 davison Trn $
= *
= * $Log:	artio.c,v $
+ * Revision 4.3.3.2  90/08/20  16:25:50  davison
+ * Fixed bug in artopen ==> nntpopen interaction.
+ * 
= * Revision 4.3.3.1  90/07/21  20:11:03  davison
= * Initial Trn Release
@@ -48,5 +51,5 @@
={
=#ifdef SERVER
-    nntpopen(artnum,GET_ARTICLE);
+    return nntpopen(artnum,GET_ARTICLE);
=#else
=    char artname[32];			/* filename of current article */
@@ -66,5 +69,4 @@
=    if (artfp = fopen(artname,"r"))	/* if we can open it */
=	openart = artnum;		/* remember what we did here */
-#endif /* SERVER */
=#ifdef LINKART
=    {
@@ -94,4 +96,5 @@
=#endif
=    return artfp;			/* and return either fp or NULL */
+#endif /* SERVER */
=}
=
Index: common.h
@@ -1,5 +1,8 @@
-/* $Header: common.h,v 4.3.3.1 90/07/21 20:15:23 davison Trn $
+/* $Header: common.h,v 4.3.3.2 90/08/20 16:28:32 davison Trn $
= * 
= * $Log:	common.h,v $
+ * Revision 4.3.3.2  90/08/20  16:28:32  davison
+ * Tweaked a couple rn's into trn's.
+ * 
= * Revision 4.3.3.1  90/07/21  20:15:23  davison
= * Initial Trn Release
@@ -437,5 +440,5 @@
=/* path to private executables */
=#ifndef RNLIB		/* ~, %x and %l only */
-#   define RNLIB "%x/rn"
+#   define RNLIB "%x/trn"
=#endif
=
@@ -737,5 +740,5 @@
=#ifndef CANCELHEADER
=#ifdef INTERNET
-#   define CANCELHEADER "Newsgroups: %n\nSubject: cmsg cancel %i\nReferences: %R\nDistribution: %D\nOrganization: %o\n\nThis message was cancelled from within rn.\n"
+#   define CANCELHEADER "Newsgroups: %n\nSubject: cmsg cancel %i\nReferences: %R\nDistribution: %D\nOrganization: %o\n\nThis message was cancelled from within trn.\n"
=#else
=#   define CANCELHEADER "Newsgroups: %n\nSubject: cmsg cancel %i\nReferences: %R\nDistribution: %D\nOrganization: %o\n"
Index: intrp.c
@@ -1,5 +1,8 @@
-/* $Header: intrp.c,v 4.3.3.1 90/07/21 20:20:13 davison Trn $
+/* $Header: intrp.c,v 4.3.3.2 90/08/20 16:29:08 davison Trn $
= *
= * $Log:	intrp.c,v $
+ * Revision 4.3.3.2  90/08/20  16:29:08  davison
+ * Added HOSTFILE handling.  Add OURDOMAIN if site has no '.'
+ * 
= * Revision 4.3.3.1  90/07/21  20:20:13  davison
= * Initial Trn Release
@@ -152,4 +155,15 @@
=    /* name of this site (%H) */
=
+#ifdef HOSTFILE
+    if ((tmpfp = fopen(HOSTFILE,"r")) == NULL) {
+	hostname = "unknown";
+	printf("Warning: Couldn't open %s to determine hostname!\n", HOSTFILE); 
+    } else {
+	fgets(buf, sizeof(buf), tmpfp);
+	buf[strlen(buf)-1] = 0;
+	hostname = savestr(buf);
+	fclose(tmpfp);
+    }
+#else
=#ifdef GETHOSTNAME
=    gethostname(buf,sizeof buf);
@@ -177,5 +191,12 @@
=#endif
=#endif
-    sitename = savestr(SITENAME);
+#endif
+#ifdef OURDOMAIN
+    if (index(SITENAME,'.') == NULL) {
+	sprintf(buf, "%s.%s", SITENAME, OURDOMAIN);
+	sitename = savestr(buf);
+    } else
+#endif
+	sitename = savestr(SITENAME);
=}
=
Index: mbox.saver.SH
@@ -5,7 +5,10 @@
=$spitshell >mbox.saver <<!GROK!THIS!
=$startsh
-# $Header: mbox.saver.SH,v 4.3.2.2 90/03/17 20:44:54 sob Exp $
+# $Header: mbox.saver.SH,v 4.3.3.1 90/08/20 16:30:28 davison Trn $
=# 
=# $Log:	mbox.saver.SH,v $
+# Revision 4.3.3.1  90/08/20  16:30:28  davison
+# Added support for MMDF format mailboxes.
+# 
=# Revision 4.3.2.2  90/03/17  20:44:54  sob
=# Modify Article header to place the colon after Article.
@@ -36,8 +39,24 @@
=export PATH || (echo "OOPS, this isn't sh.  Desperation time.  I will feed myself to sh."; sh \$0; kill \$\$)
=
+!GROK!THIS!
+case $mboxchar in
+"$CTRLA")
+    $spitshell >>mbox.saver <<!GROK!THIS!
+( $echo "$CTRLA$CTRLA$CTRLA$CTRLA"
+  if $test "\$5" = 0 -a ! "\$4" = 0 ; then
+    $echo "Article: \$4 of \$6"
+  fi
+  $tail +\$5c \$1
+  $echo ""
+  $echo ""
+  $echo "$CTRLA$CTRLA$CTRLA$CTRLA" ) >> \$7
+!GROK!THIS!
+    ;;
+*)
+    $spitshell >>mbox.saver <<!GROK!THIS!
=( $echo "\$8"
-  case "\$5" in
-  0) $echo "Article: \$4 of \$6" ;;
-  esac
+  if $test "\$5" = 0 -a ! "\$4" = 0 ; then
+    $echo "Article: \$4 of \$6"
+  fi
=  $tail +\$5c \$1 | $sed "s/^From />From /"
=  $echo ""
@@ -44,4 +63,6 @@
=  $echo "" ) >> \$7
=!GROK!THIS!
+    ;;
+esac
=$eunicefix mbox.saver
=chmod 755 mbox.saver
Index: mt-process.c
@@ -1,5 +1,8 @@
-/* $Header: mt-process.c,v 4.3.3.1 90/07/28 18:04:45 davison Trn $
+/* $Header: mt-process.c,v 4.3.3.2 90/08/20 16:40:31 davison Trn $
=**
=** $Log:	mt-process.c,v $
+** Revision 4.3.3.2  90/08/20  16:40:31  davison
+** Added check of caught_interrupt flag into main loops.
+** 
=** Revision 4.3.3.1  90/07/28  18:04:45  davison
=** Initial Trn Release
@@ -76,5 +79,4 @@
=	i = first_article;
=    }
-    processed_groups++;
=    added_count = last_article - i + 1;
=    expired_count = 0;
@@ -81,4 +83,7 @@
=
=    for( ; i <= last_article; i++ ) {
+	if( caught_interrupt ) {
+	    return;
+	}
=#ifdef SERVER
=	sprintf( buff, "HEAD %ld", (long)i );
@@ -225,4 +230,7 @@
=	expire( first_article );
=    }
+    if( caught_interrupt ) {
+	return;
+    }
=    trim_roots();
=    order_roots();
@@ -251,4 +259,7 @@
=	next_domain = domain->link;
=	for( article = domain->ids; article; article = next_art ) {
+	    if( caught_interrupt ) {
+		return;
+	    }
=	    next_art = article->id_link;
=	    if( !article->subject || (article->flags & NEW_ARTICLE) ) {
Index: mt.check.SH
@@ -5,7 +5,10 @@
=$spitshell >mt.check <<!GROK!THIS!
=$startsh
-# $Header: mt.check.SH,v 4.3.3.1 90/06/20 23:00:07 davison Trn $
+# $Header: mt.check.SH,v 4.3.3.2 90/08/20 16:42:10 davison Trn $
=#
=# $Log:	mt.check.SH,v $
+# Revision 4.3.3.2  90/08/20  16:42:10  davison
+# Changed email address.
+# 
=# Revision 4.3.3.1  90/06/20  23:00:07  davison
=# Initial Trn Release
@@ -39,7 +42,7 @@
=
=The following errors were reported in mt.log.  Please report this fact
-to Wayne Davison (davison%drivax at uunet.uu.net) for him to fix.  All of
-the affected newsgroups can not be updated until this bug is fixed, or
-the offending articles are expired.
+to Wayne Davison (davison at dri.com or ...!uunet!drivax!davison) for his
+attention.  The affected newsgroups can't be updated until this bug is
+fixed, or the offending articles are expired.
=
=EOT
Index: mthreads.1
@@ -1,5 +1,8 @@
-''' $Header: mthreads.1,v 4.3.3.1 90/07/21 20:03:37 davison Trn $
+''' $Header: mthreads.1,v 4.3.3.2 90/08/20 16:42:32 davison Trn $
=''' 
=''' $Log:	mthreads.1,v $
+''' Revision 4.3.3.2  90/08/20  16:42:32  davison
+''' Document new command-line interface.
+''' 
=''' Revision 4.3.3.1  90/07/21  20:03:37  davison
=''' Initial Trn Release
@@ -51,5 +54,5 @@
=mthreads - threaded database manager for trn
=.SH SYNOPSIS
-.B mthreads [-d[MM]] [-e[HHMM]] [-f] [-v] [hierarchy]
+.B mthreads [-d[MM]] [-e[HHMM]] [-aDfknv] [hierarchy_list]
=.SH DESCRIPTION
=.I Mthreads
@@ -63,17 +66,19 @@
=needs to be run
=periodically \*(-- either in single-pass mode out of cron,
-or in daemon mode out of your boot script \*(-- to update the thread
+or in daemon mode out of the boot script \*(-- to update the thread
=information whenever new news is received.
-If a site only gets one feed a day and doesn't need local postings processed
-throughout the day, running
+A site that gets its news feed during the night and doesn't need local
+postings processed throughout the day can run
+.I mthreads
+in single-pass mode once a day.
+If more processing is needed, either run
=.I mthreads
-in single-pass mode once a day may be all that is needed.
-Otherwise, daemon mode should be used, where mthreads forks off
-a background process and wakes up every 10 minutes (by default) to check if
-the active file has been updated.
+more often or run it in daemon mode.
+In daemon mode, a background process is forked off that wakes up every 10
+minutes (by default) to check if the active file has been updated.
=.SH INSTALLATION
=.I Mthreads
=in installed in the RNLIB directory chosen during configuration.
-When it is run for first time, it will automatically create a file called
+When it is run for the first time, it will automatically create a file called
=.I active2
=in the same directory.
@@ -80,45 +85,56 @@
=This file is essentially a copy of the active file that keeps the newsgroup
=totals from the last run in one place.
-The active2 file is also used to limit the number of groups to be processed
-into thread files.
-If groups need to be limited for testing purposes, use
+It is also used to choose which groups are to be processed into thread files.
+All groups start out as \*(L"unthreaded\*(R" unless they are turned on with
=a command like:
=.IP
-mthreads news.software
+mthreads all
=.PP
-to process only the groups that match the given hierarchy name.
-If mthreads is to be more selective or limit the groups on a more permanent
-basis, edit the fourth field of the
-.I active2
-file to change the single character (e.g. \*(L'y\*(R', \*(L'm\*(R',
-etc). to upper-case.
-If the active2 file hasn't been created yet, use the command:
+which would create thread file for all the groups.
+For testing purposes it is a good idea to start out small with a command
+like:
=.IP
-mthreads namethatwontmatch
-.PP
-to create a valid active2 file without processing any groups.
-See also the
-.B \-f
-option if an active2 file has invalid min/max
-fields (such as if the active file has been directly copied to active2).
-.PP
-If no further processing of a group is desired, change its entry in active2
-to have the upper-case 4th field and then be sure to delete its thread file.
-This is the only time that
-.I mthreads
-won't be able to handle the thread file upkeep automatically.
-(It knows to delete thread files when the group goes empty, when the group
-gets removed, and when it gets x-ed out in the active file.)
+mthreads news
+.PP
+which would thread only the news hierarchy.
+Thread processing can be turned on or off for individual groups or entire
+hierarchies by specifying the groups in a syntax very similar to that used
+in the sys file.
+For example, to turn on all of soc and talk except for talk.politics, and
+to turn off news.lists, use the following command once:
+.IP
+mthreads soc,talk,!talk.politics,!news.lists
+.PP
+If mthreads complains that another mthreads process is already running,
+it can be killed with the command:
+.IP
+mthreads -k
+.PP
+and then repeat the prior command after giving it a little time to die.
+.PP
+Once all the desired groups are turned on, it is not necessary to
+specify a hierarchy list for the normal functioning of mthreads.
+It can be used, however, to customize which new groups get turned on
+as they are created.
=.SH LOGGING
=As mthreads executes, some status information (including error messages) 
=is placed in
-the file mt.log in your RNLIB directory.
-Mt.log can grow without bounds, and should be scanned periodically for
+the file mt.log in the RNLIB directory.
+This file will grow without bounds, and should be scanned periodically for
=errors, and trimmed in size when it grows too large.
=See the shell script
=.I mt.check
-for a simple example that can be run on a daily basis.
+for an mt.log maintainer that will send mail if it finds database errors.
=.SH OPTIONS
=.TP 5
+.B \-a
+is used to automatically turn on thread processing for new news groups as
+they are created.
+The default is to leave new groups unthreaded.
+.TP 5
+.B \-D
+specifies a debugging mode where only the groups mentioned on the
+command-line are processed \*(-- all other groups are left unchanged.
+.TP 5
=.B \-d
=is used to specify the daemon mode, where
@@ -154,7 +170,21 @@
=to open each and every thread file to see which ones really need to be
=updated, not just the ones that differ in the active/active2 comparison.
-This should only be used when setting up initially
-or when you are hacking around with the thread files.
+It will also remove any extraneous thread files from unthreaded groups
+(which should only occur if you manually change the active2 file).
+This option should only be used when manipulating the thread files in
+unorthodox ways.
=.TP 5
+.B -k
+can be used to terminate the currently running mthreads, just as if it
+had received a terminate signal.
+When this option is specified, no other activity is performed.
+.TP 5
+.B -n
+tells
+.I mthreads
+that no actual processing of thread files is to be performed.
+This can be used to just adjust which groups are to be processed, without
+actually doing any of the processing right away.
+.TP 5
=.B -v
=selects additional levels of verbosity in the log file.
@@ -166,12 +196,14 @@
=Add a second and a third for even more (useless?) information.
=.TP 5
-.B hierarchy
-The scope of the groups processec can be limited
-by specifying one hierarchy (e.g. \*(L"news\*(R",
-\*(L"comp.sys.ibm.pc.d\*(R").
-To run mthreads on a limited set of newsgroups in normal operation
-edit the active2 file (NOT the active file!) and change the fourth
-field to be upper-case for each group that should not be processed
-(e.g. \*(L'Y\*(R', \*(L'M\*(R', etc.)
+.B hierarchy_list
+The hierarchy list is used to turn thread processing on or off for the listed
+groups.
+The groups are specified in a manner very similar to the news software's
+sys file:  \*(L"news\*(R" matches all groups in news; \*(L"!news\*(R" excludes
+all groups in news; \*(L"comp.all.ibm.pc,!comp.all.ibm.pc.all\*(L" matches both
+comp.sys.ibm.pc and comp.binaries.ibm.pc, but not comp.binaries.ibm.pc.d.
+.Sp
+The hierarchy_list is also used in conjunction with the debug flag to only
+process one or more groups for testing purposes.
=.SH OUTPUT
=When
@@ -188,5 +220,5 @@
=	\&':' = group processed -- no change
=.br
-	\&'+' = group processed
+	\&'#' = group processed
=.br
=	\&'-' = group processed -- is now empty
@@ -215,8 +247,28 @@
=This file contains the byte-order of the machine that generated the database,
=and needs to be removed to truly start from scratch.
-.SH ERROR HANDLING
+An easy way to get
+.I mthreads
+to remove all the files except for db.init is to specify the command:
+.IP
+mthreads !all
+.PP
+This also turns off thread processing for all groups.
+.SH "ERROR HANDLING"
=If the active2 file is removed or corrupted, it will
-be automatically repaired in the normal course of operation.
-Missing thread files are automatically re-built.
+be automatically rebuilt in the normal course of operation.
+The record of which groups should be threaded will be lost, however.
+Missing/corrupted thread files are automatically re-built.
+.SH EXAMPLES
+Recommended commands to run on a regular basis are:
+.IP
+mthreads -adve0630
+.PP
+to start up an mthreads daemon in verbose logging mode that automatically
+threads new groups and performs an extended expire at 6:30 am, or:
+.IP
+mthreads -e >/dev/null
+.PP
+to run an mthreads single-pass with extended expire that leaves new groups
+unthreaded.
=.SH FILES
=/usr/lib/news/active
@@ -232,3 +284,3 @@
=Lots of thread data files.
=.SH AUTHOR
-Wayne Davison <davison at drivax.UUCP> <davison%drivax at uunet.uu.net>
+Wayne Davison <davison at dri.com> <uunet!drivax!davison>
Index: mthreads.c
@@ -1,5 +1,8 @@
-/* $Header: mthreads.c,v 4.3.3.1 90/07/24 22:24:17 davison Trn $
+/* $Header: mthreads.c,v 4.3.3.2 90/08/20 16:43:19 davison Trn $
=**
=** $Log:	mthreads.c,v $
+** Revision 4.3.3.2  90/08/20  16:43:19  davison
+** Implemented new command-line interface and database upgrading.
+** 
=** Revision 4.3.3.1  90/07/24  22:24:17  davison
=** Initial Trn Release
@@ -13,9 +16,9 @@
=** When fully updated, the two files should be identical.  This gives us
=** quick access to the last processed high/low counts without opening
-** each data file, PLUS it allows tn to use the fake active file as if it
+** each data file, PLUS it allows trn to use the fake active file as if it
=** were the real thing to keep it from seeing articles before they are
-** processed.  If the active2 file is removed or corrupted, it should
-** be automatically repaired in the normal course of operation.  We update
-** the file IN PLACE so that tn can keep it open all the time.  Normally
+** processed.  If the active2 file is removed or corrupted, it will be
+** automatically repaired in the normal course of operation.  We update
+** the file IN PLACE so that trn can keep it open all the time.  Normally
=** the size of the file does not change, so it is easy to do.  In those
=** rare instances where a news admin shuffles the real active file, we
@@ -22,5 +25,5 @@
=** take it all in stride by throwing a little memory at the problem.
=**
-** Usage:  mthreads [-d[MM]] [-e[HHMM]] [-f] [-v] [hierarchy]
+** Usage:  mthreads [-d[MM]] [-e[HHMM]] [-aDfknv] [hierarchy_list]
=*/
=
@@ -47,4 +50,7 @@
=static char line2[256];
=
+/* If you want to change the field size, do it once and then leave it alone. */
+char fmt_active2[] = "%s %06ld %06ld %c\n";
+
=char *filename;
=
@@ -61,10 +67,9 @@
=ACTIVE_LINE *line_root = Nullact, *last_line = Nullact, *pline = Nullact;
=
-bool force_flag = FALSE, grevious_error;
-int daemon_delay = 0;
+bool force_flag = FALSE, kill_mthreads = FALSE, no_processing = FALSE;
+bool add_new = FALSE, rebuild = FALSE, grevious_error;
+int daemon_delay = 0, log_verbosity = 0, debug = 0;
=long expire_time = 0;
-int log_verbosity = 0;
-char *hierarchy = "all";
-int match_len = 0;
+char *hierarchy_list = NULL;
=long truncate_len = -1;
=
@@ -82,4 +87,10 @@
=#define TIMER_DEFAULT (10 * 60)
=
+int added_groups, removed_groups, action;
+
+#define NG_DEFAULT	0
+#define NG_MATCH	1
+#define NG_SKIP		2
+
=#ifdef SERVER
=char *server;
@@ -102,4 +113,10 @@
=	    while( *++*argv ) {
=		switch( **argv ) {
+		case 'a':		/* automatically thread new groups */
+		    add_new = TRUE;
+		    break;
+		case 'D':
+		    debug++;
+		    break;
=		case 'd':
=		    if( *++*argv <= '9' && **argv >= '0' ) {
@@ -145,4 +162,10 @@
=		    force_flag = TRUE;
=		    break;
+		case 'k':
+		    kill_mthreads = TRUE;
+		    break;
+		case 'n':
+		    no_processing = TRUE;
+		    break;
=		case 'v':
=		    log_verbosity++;
@@ -154,10 +177,9 @@
=	    }
=	} else {
-	    if( match_len ) {
-		fprintf( stderr, "Only one hierarchy name is currently allowed.\n" );
+	    if( hierarchy_list ) {
+		fprintf( stderr, "Specify the newsgroups in one comma-separated list.\n" );
=		exit( 1 );
=	    }
-	    hierarchy = *argv;
-	    match_len = strlen( hierarchy );
+	    hierarchy_list = *argv;
=	}
=    }
@@ -204,5 +226,5 @@
=	}
=	fclose( fp_lock );
-	if( kill( otherpid, 0 ) == -1 ) {
+	if( kill( otherpid, kill_mthreads ? SIGTERM : 0 ) == -1 ) {
=	    if( unlink( filename ) == -1 ) {
=		fprintf( stderr, "unable to unlink lockfile %s\n", filename );
@@ -210,9 +232,16 @@
=		exit( 1 );
=	    }
-	    goto dolink;
+	    if( !kill_mthreads ) {
+		goto dolink;
+	    }
=	}
-	fprintf( stderr, "mthreads is already running.\n" );
=	unlink( line );
-	exit( 1 );
+	if( kill_mthreads ) {
+	    fprintf( stderr, "killing currently running mthreads.\n" );
+	    exit( 0 );
+	} else {
+	    fprintf( stderr, "mthreads is already running.\n" );
+	    exit( 1 );
+	}
=    }
=
@@ -219,4 +248,9 @@
=    unlink( line );			/* remove temporary LOCK.<pid> file */
=
+    if( kill_mthreads ) {
+	fprintf( stderr, "mthreads is not running.\n" );
+	exit( 1 );
+    }
+
=    /* Open our log file */
=    filename = file_exp( "%X/mt.log" );
@@ -245,5 +279,5 @@
=#ifdef lint
=    alarm_handler();			/* foolishness for lint's sake */
-    interrupt(14);
+    interrupt( 14 );
=#endif
=
@@ -251,8 +285,9 @@
=    filename = file_exp( "%X/db.init" );
=    if( (fp_lock = fopen( filename, "r")) == Nullfp
-     || fread( &mt_bmap, 1, sizeof (BMAP), fp_lock ) < sizeof (BMAP) ) {
+     || fread( &mt_bmap, 1, sizeof (BMAP), fp_lock ) < sizeof (BMAP)-1 ) {
=	if( fp_lock != Nullfp ) {
=	    fclose( fp_lock );
=	}
+     write_db_init:
=	mybytemap( &mt_bmap );
=	if( (fp_lock = fopen( filename, "w" )) == Nullfp ) {
@@ -260,5 +295,5 @@
=	    exit( 1 );
=	}
-	mt_bmap.version = 1;
+	mt_bmap.version = DB_VERSION;
=	fwrite( &mt_bmap, 1, sizeof (BMAP), fp_lock );
=	fclose( fp_lock );
@@ -266,4 +301,15 @@
=	int i;
=
+	fclose( fp_lock );
+	if( mt_bmap.version != DB_VERSION ) {
+	    if( mt_bmap.version == DB_VERSION-1 ) {
+		rebuild = TRUE;
+		log_entry( "Upgrading database to version %d.\n", DB_VERSION );
+		goto write_db_init;
+	    }
+	    log_entry( "** Database is not the right version (%d instead of %d) **\n",
+		mt_bmap.version, DB_VERSION );
+	    exit( 1 );
+	}
=	mybytemap( &my_bmap );
=	for( i = 0; i < sizeof (LONG); i++ ) {
@@ -276,5 +322,4 @@
=	    }
=	}
-	fclose( fp_lock );
=    }
=
@@ -289,5 +334,5 @@
=    /* If we're not in daemon mode, run through once and quit. */
=    if( !daemon_delay ) {
-	log_entry( "mthreads single pass for '%s'\n", hierarchy );
+	log_entry( "mthreads single pass started.\n" );
=	setbuf( stdout, Nullch );
=	extra_expire = (expire_time != 0);
@@ -332,5 +377,5 @@
=	}
=
-	log_entry( "mthreads daemon started for '%s'\n", hierarchy );
+	log_entry( "mthreads daemon started.\n" );
=
=#ifndef SERVER
@@ -342,5 +387,13 @@
=	alarm( TIMER_FIRST );
=	for( ;; ) {
+	    if( caught_interrupt ) {
+		wrap_it_up();
+		/* NORETURN */
+	    }
=	    pause();		/* let alarm go off */
+	    if( caught_interrupt ) {
+		wrap_it_up();
+		/* NORETURN */
+	    }
=	    alarm( 0 );
=
@@ -387,11 +440,10 @@
={
=    /* Re-open our log file, if needed */
-    if( !fp_log && !(fp_log = fopen( file_exp( "%X/mt.log" ), "a" )) ) {
-	exit( 1 );
-    }
-    if( sig == SIGTERM ) {
-	log_entry( "interrupt %d\n", sig);
-    } else {
-	log_entry( "** interrupt %d **\n", sig);
+    if( fp_log || (fp_log = fopen( file_exp( "%X/mt.log" ), "a" )) ) {
+	if( sig == SIGTERM ) {
+	    log_entry( "mthreads halted.\n", sig);
+	} else {
+	    log_entry( "** interrupt %d **\n", sig);
+	}
=    }
=    if( !daemon_delay ) {
@@ -398,6 +450,6 @@
=	printf( "interrupt %d!\n", sig );
=    }
-    /* Handle interrupt by just bugging out */
-    wrap_it_up();
+    /* Flag interrupt occurred -- main loop attempts an orderly retreat. */
+    caught_interrupt = TRUE;
=}
=
@@ -448,4 +500,8 @@
=    }
=    while( 1 ) {
+	if( caught_interrupt ) {
+	    wrap_it_up();
+	    /* NORETURN */
+	}
=	if( get_server( line, sizeof line ) < 0 ) {
=	    log_entry( "Server failed to send entire active file -- sleeping.\n" );
@@ -478,4 +534,8 @@
=	exit( 1 );
=    }
+    if( caught_interrupt ) {
+	wrap_it_up();
+	/* NORETURN */
+    }
=    if( extra_expire && log_verbosity ) {
=	log_entry( "Using enhanced expiration for this pass.\n" );
@@ -482,7 +542,6 @@
=    }
=
-    processed_groups = 0;
-    added_articles = 0;
-    expired_articles = 0;
+    processed_groups = added_groups = removed_groups = 0;
+    added_articles = expired_articles = 0;
=
=    /* Loop through entire active file. */
@@ -544,9 +603,15 @@
=			last2 = total.last;
=			first2 = total.first;
+			ch2 = 'y';
=		    } else {
-			total.last = last2 = first - 1;
+			total.last = last2 = last;
=			total.first = first2 = first;
+			if( add_new ) {
+			    ch2 = (ch == '=' ? 'x' : ch);
+			    added_groups++;
+			} else {
+			    ch2 = (ch == '=' ? 'X' : toupper( ch ));
+			}
=		    }
-		    ch2 = (ch == 'x' ? 'n' : ch);
=		    data_file_open++;		/* (1 == empty, 2 == open) */
=		    break;
@@ -593,15 +658,42 @@
=	    }
=	}
+	if( rebuild ) {
+	    unlink( thread_name( line ) );
+	}
=	update_successful = FALSE;
-	if( match_len && strnNE( line, hierarchy, match_len ) ) {
-	    dont_read_data( data_file_open );		/* skip non-matches */
-	} else if( ch == 'x' ) {
-	    if( !daemon_delay ) {			/* skip 'x'ed groups */
+	if( hierarchy_list ) {
+	    action = ngmatch( hierarchy_list, line );
+	} else {
+	    action = NG_DEFAULT;
+	}
+	switch( action ) {
+	case NG_DEFAULT:
+	    if( ch2 < 'a' ) {
+		action = NG_SKIP;
+	    } else {
+		action = NG_MATCH;
+	    }
+	    break;
+	case NG_MATCH:				/* add if unthreaded */
+	    if( ch2 < 'a' ) {
+		last2 = first2 - 1;
+		added_groups++;
+	    }
+	    break;
+	case NG_SKIP:				/* remove if threaded */
+	    if( ch2 >= 'a' && !debug ) {
+		unlink( thread_name( line ) );
+		removed_groups++;
+	    }
+	    break;
+	}
+	if( caught_interrupt || (debug && action != NG_MATCH) ) {
+	    dont_read_data( data_file_open );	/* skip silently */
+	} else if( ch == 'x' || ch == '=' ) {
+	    if( !daemon_delay ) {		/* skip 'x'ed groups */
=		putchar( 'x' );
=	    }
-	    dont_read_data( data_file_open );
-	    if( ch2 == 'X' ) {
-		ch = ch2;
-	    } else if( ch2 != 'x' ) {
+	    ch = (action == NG_SKIP ? 'X' : 'x');
+	    if( (ch2 >= 'a' && ch2 != 'x') || force_flag ) {
=		/* Remove thread file if group is newly 'x'ed out */
=		unlink( thread_name( line ) );
@@ -608,21 +700,22 @@
=	    }
=	    update_successful = TRUE;
-	} else if( ch2 < 'a' ) {
-	    /* This group is marked 'Y', 'M', 'N', or '=' in active2.
-	    ** Don't process it.
-	    */
+	    dont_read_data( data_file_open );
+	} else if( action == NG_SKIP ) {	/* skip excluded groups */
=	    if( !daemon_delay ) {
=		putchar( 'X' );
=	    }
-	    dont_read_data( data_file_open );
-	    if( ch2 != '=' ) {
-		if( ch != '=' ) {
-		    ch = toupper( ch );
-		} else {
-		    ch = ch2;
-		}
+	    ch = toupper( ch );
+	    if( force_flag ) {
+		unlink( thread_name( line ) );
=	    }
=	    update_successful = TRUE;
-	} else if( !force_flag && !extra_expire
+	    dont_read_data( data_file_open );
+	} else if( no_processing ) {
+	    if( !daemon_delay ) {
+		putchar( ',' );
+	    }
+	    ch2 = ch;
+	    dont_read_data( data_file_open );
+	} else if( !force_flag && !extra_expire && !rebuild
=	 && first == first2 && last == last2 ) {
=	    /* We're up-to-date here.  Skip it. */
@@ -630,6 +723,6 @@
=		putchar( '.' );
=	    }
-	    dont_read_data( data_file_open );
=	    update_successful = TRUE;
+	    dont_read_data( data_file_open );
=	} else {
=	    /* Looks like we need to process something. */
@@ -685,5 +778,8 @@
=		grevious_error = FALSE;
=		process_articles( first, last );
-		if( !added_count && !expired_count && last == last2 ) {
+		processed_groups++;
+		if( caught_interrupt ) {
+		    processed_groups--;	/* save nothing -- no update */
+		} else if( !added_count && !expired_count && last == last2 ) {
=		    (void) write_data( Nullch );
=		    if( !daemon_delay ) {
@@ -706,5 +802,5 @@
=			expired_articles += expired_count;
=			if( !daemon_delay ) {
-			    putchar( '+' );
+			    putchar( '#' );
=			}
=			update_successful = TRUE;
@@ -720,15 +816,13 @@
=			    putchar( '!' );
=			}
-		    }
-		}
-	    }
-	}
+		    }/* if */
+		}/* if */
+	    }/* if */
+	}/* if */
=	/* Finally, update the active2 entry for this newsgroup. */
=	if( update_successful ) {
-	    fprintf( fp_active3, "%s %06ld %06ld %c\n",
-		line, last, first, ch );
+	    fprintf( fp_active3, fmt_active2, line, last, first, ch );
=	} else {
-	    fprintf( fp_active3, "%s %06ld %06ld %c\n",
-		line, last2, first2, ch2 );
+	    fprintf( fp_active3, fmt_active2, line, last2, first2, ch2 );
=	}
=    }/* for */
@@ -794,5 +888,167 @@
=	fputs( line, stdout );
=    }
+    if( added_groups ) {
+	sprintf( line, "Turned %d group%s on.\n", added_groups,
+		added_groups == 1 ? nullstr : "s" );
+	log_entry( line );
+	if( !daemon_delay ) {
+	    fputs( line, stdout );
+	}
+    }
+    if( removed_groups ) {
+	sprintf( line, "Turned %d group%s off.\n", removed_groups,
+		removed_groups == 1 ? nullstr : "s" );
+	log_entry( line );
+	if( !daemon_delay ) {
+	    fputs( line, stdout );
+	}
+    }
=    extra_expire = FALSE;
+    rebuild = FALSE;
+}
+
+/*
+** ngmatch - newsgroup name matching
+**
+** returns NG_MATCH for a positive patch, NG_SKIP for a negative match,
+** and NG_DEFAULT if the group doesn't match at all.
+**
+** "all" in a pattern is a wildcard that matches exactly one word;
+** it does not cross "." (NGDELIM) delimiters.
+**
+** This matching code was borrowed from C news.
+*/
+
+#define ALL "all"			/* word wildcard */
+
+#define NGNEG '!'
+#define NGSEP ','
+#define NGDELIM '.'
+
+int
+ngmatch( ngpat, grp )
+char *ngpat, *grp;
+{
+    register char *patp;		/* point at current pattern */
+    register char *patcomma;
+    register int depth;
+    register int faildeepest = 0, hitdeepest = 0;	/* in case no match */
+    register bool negation;
+
+    for( patp = ngpat; patp != Nullch; patp = patcomma ) {
+	negation = FALSE;
+	patcomma = index( patp, NGSEP );
+	if( patcomma != Nullch ) {
+	    *patcomma = '\0';	/* will be restored below */
+	}
+	if( *patp == NGNEG ) {
+	    ++patp;
+	    negation = TRUE;
+	}
+	depth = onepatmatch( patp, grp ); /* try 1 pattern, 1 group */
+	if( patcomma != Nullch ) {
+	    *patcomma++ = NGSEP;	/* point after the comma */
+	}
+	if( depth == 0 ) {		/* mis-match */
+	    ;				/* ignore it */
+	} else if( negation ) {
+	    /* record depth of deepest negated matched word */
+	    if( depth > faildeepest ) {
+		faildeepest = depth;
+	    }
+	} else {
+	    /* record depth of deepest plain matched word */
+	    if( depth > hitdeepest ) {
+		hitdeepest = depth;
+	    }
+	}
+    }
+    if( hitdeepest > faildeepest ) {
+	return NG_MATCH;
+    } else if( faildeepest ) {
+	return NG_SKIP;
+    } else {
+	return NG_DEFAULT;
+    }
+}
+
+/*
+** Match a pattern against a group by looking at each word of pattern in turn.
+**
+** On a match, return the depth (roughly, ordinal number * k) of the rightmost
+** word that matches.  If group runs out first, the match fails; if pattern
+** runs out first, it succeeds.  On a failure, return zero.
+*/
+int
+onepatmatch( patp, grp )
+char *patp, *grp;
+{
+    register char *rpatwd;		/* used by word match (inner loop) */
+    register char *patdot, *grdot;	/* point at dots after words */
+    register char *patwd, *grwd;	/* point at current words */
+    register int depth = 0;
+
+    for( patwd = patp, grwd = grp;
+	 patwd != Nullch && grwd != Nullch;
+	 patwd = patdot, grwd = grdot
+    ) {
+	register bool match = FALSE;
+	register int incr = 20;
+
+	/* null-terminate words */
+	patdot = index(patwd, NGDELIM);
+	if( patdot != Nullch ) {
+	    *patdot = '\0';		/* will be restored below */
+	}
+	grdot = index( grwd, NGDELIM );
+	if( grdot != Nullch ) {
+	    *grdot = '\0';		/* will be restored below */
+	}
+	/*
+	 * Match one word of pattern with one word of group.
+	 * A pattern word of "all" matches any group word,
+	 * but isn't worth as much.
+	 */
+#ifdef FAST_STRCMP
+	match = STREQ( patwd, grwd );
+	if( !match && STREQ( patwd, ALL ) ) {
+	    match = TRUE;
+	    --incr;
+	}
+#else
+	for( rpatwd = patwd; *rpatwd == *grwd++; ) {
+	    if( *rpatwd++ == '\0' ) {
+		match = TRUE;		/* literal match */
+		break;
+	    }
+	}
+	if( !match ) {
+	    /* ugly special case match for "all" */
+	    rpatwd = patwd;
+	    if( *rpatwd++ == 'a' && *rpatwd++ == 'l'
+	     && *rpatwd++ == 'l' && *rpatwd   == '\0' ) {
+		match = TRUE;
+		 --incr;
+	    }
+	}
+#endif				/* FAST_STRCMP */
+
+	if( patdot != Nullch ) {
+	    *patdot++ = NGDELIM;	/* point after the dot */
+	}
+	if( grdot != Nullch ) {
+	    *grdot++ = NGDELIM;
+	}
+	if( !match ) {
+	    depth = 0;		/* words differed - mismatch */
+	    break;
+	}
+	depth += incr;
+    }
+    /* if group name ran out before pattern, then match fails */
+    if( grwd == Nullch && patwd != Nullch ) {
+	depth = 0;
+    }
+    return depth;
=}
=
Index: mthreads.h
@@ -1,5 +1,8 @@
-/* $Header: mthreads.h,v 4.3.3.1 90/06/20 22:55:27 davison Trn $
+/* $Header: mthreads.h,v 4.3.3.2 90/08/20 16:44:29 davison Trn $
=**
=** $Log:	mthreads.h,v $
+** Revision 4.3.3.2  90/08/20  16:44:29  davison
+** New entries for new command-line interface.
+** 
=** Revision 4.3.3.1  90/06/20  22:55:27  davison
=** Initial Trn Release
@@ -18,4 +21,5 @@
=EXT int expired_articles, expired_count;
=EXT bool extra_expire INIT(FALSE);
+EXT bool caught_interrupt INIT(FALSE);
=
=EXT char *strings INIT(0);
@@ -42,4 +46,6 @@
=};
=#endif
+
+int ngmatch(), onepatmatch();
=
=void log_entry(), log_error();
Index: newsnews.SH
@@ -24,5 +24,5 @@
=will again be displayed, just once for each person.
=
-Wayne Davison	davison%drivax at uunet.uu.net
+Wayne Davison	davison at dri.com
=!GROK!THIS!
=$eunicefix newsnews
Index: ng.c
@@ -1,5 +1,8 @@
-/* $Header: ng.c,v 4.3.3.1 90/07/21 20:27:17 davison Trn $
+/* $Header: ng.c,v 4.3.3.2 90/08/20 16:03:45 davison Trn $
= *
= * $Log:	ng.c,v $
+ * Revision 4.3.3.2  90/08/20  16:03:45  davison
+ * Fixed bug in backpage code.
+ * 
= * Revision 4.3.3.1  90/07/21  20:27:17  davison
= * Initial Trn Release
@@ -1450,6 +1453,7 @@
=	    target = topline - (LINES - 2);
=	    artline = topline;
-	    while (artline >= 0 && artline > target && vrdary(artline-1) >= 0)
+	    if (artline >= 0) do {
=		artline--;
+	    } while(artline >= 0 && artline > target && vrdary(artline-1) >= 0);
=	    topline = artline;
=	    if (artline < 0)
Index: ngstuff.c
@@ -1,5 +1,8 @@
-/* $Header: ngstuff.c,v 4.3.3.1 90/07/21 20:29:12 davison Trn $
+/* $Header: ngstuff.c,v 4.3.3.2 90/08/20 18:29:08 davison Trn $
= *
= * $Log:	ngstuff.c,v $
+ * Revision 4.3.3.2  90/08/20  18:29:08  davison
+ * Expanded path arrays for consistancy.
+ * 
= * Revision 4.3.3.1  90/07/21  20:29:12  davison
= * Initial Trn Release
@@ -54,5 +57,5 @@
=    bool interactive = (buf[1] == FINISHCMD);
=    bool docd;
-    char whereiam[256];
+    char whereiam[512];
=
=    if (!finish_command(interactive))	/* get remainder of command */
@@ -115,5 +118,5 @@
=    else {
=	bool docd = (instr(buf,"-d") != Nullch);
- 	char whereami[256];
+ 	char whereami[512];
= 
=	if (docd)
Index: rcln.c
@@ -1,5 +1,8 @@
-/* $Header: rcln.c,v 4.3.3.1 90/06/20 22:39:19 davison Trn $
+/* $Header: rcln.c,v 4.3.3.2 90/08/20 16:46:05 davison Trn $
= *
= * $Log:	rcln.c,v $
+ * Revision 4.3.3.2  90/08/20  16:46:05  davison
+ * Removed extraneous xref boundary check.
+ * 
= * Revision 4.3.3.1  90/06/20  22:39:19  davison
= * Initial Trn Release
@@ -84,5 +87,5 @@
=	set_toread(ngnum);		/* the list due to expires if we */
=					/* have not yet. */
-#ifdef DEBUGGING
+#if defined(DEBUGGING) && !defined(USETHREADS)
=    if (artnum > ngmax[ngnum] + 10	/* allow for incoming articles */
=       ) {
@@ -332,5 +335,5 @@
=    ART_NUM newmax;
=
-#ifdef DEBUGGING
+#if defined(DEBUGGING) && !defined(USETHREADS)
=    ngmax[ngnum] = ngsize;		/* for checking out-of-range Xrefs */
=#endif
Index: rcln.h
@@ -1,5 +1,8 @@
-/* $Header: rcln.h,v 4.3 85/05/01 11:45:52 lwall Exp $
+/* $Header: rcln.h,v 4.3.3.1 90/08/20 16:47:22 davison Trn $
= *
= * $Log:	rcln.h,v $
+ * Revision 4.3.3.1  90/08/20  16:47:22  davison
+ * Removed ngmax array.
+ * 
= * Revision 4.3  85/05/01  11:45:52  lwall
= * Baseline for release with 4.3bsd.
@@ -7,5 +10,5 @@
= */
=
-#ifdef DEBUGGING
+#if defined(DEBUGGING) && !defined(USETHREADS)
=EXT ART_NUM ngmax[MAXRCLINE];
=#endif
Index: rcstuff.c
@@ -1,5 +1,8 @@
-/* $Header: rcstuff.c,v 4.3.3.1 90/06/20 22:39:28 davison Trn $
+/* $Header: rcstuff.c,v 4.3.3.2 90/08/20 16:47:44 davison Trn $
= *
= * $Log:	rcstuff.c,v $
+ * Revision 4.3.3.2  90/08/20  16:47:44  davison
+ * Removed ngmax array.
+ * 
= * Revision 4.3.3.1  90/06/20  22:39:28  davison
= * Initial Trn Release
@@ -479,5 +482,5 @@
=    ACT_POS tmpsoftptr;
=    register NG_NUM i;
-#ifdef DEBUGGING
+#if defined(DEBUGGING) && !defined(USETHREADS)
=    ART_NUM tmpngmax;
=#endif
@@ -502,5 +505,5 @@
=	tmprcnums = rcnums[ngx];
=	tmpsoftptr = softptr[ngx];
-#ifdef DEBUGGING
+#if defined(DEBUGGING) && !defined(USETHREADS)
=	tmpngmax = ngmax[ngx];
=#endif
@@ -514,5 +517,5 @@
=	    rcnums[i-1] = rcnums[i];
=	    softptr[i-1] = softptr[i];
-#ifdef DEBUGGING
+#if defined(DEBUGGING) && !defined(USETHREADS)
=	    ngmax[i-1] = ngmax[i];
=#endif
@@ -526,5 +529,5 @@
=	rcnums[nextrcline-1] = tmprcnums;
=	softptr[nextrcline-1] = tmpsoftptr;
-#ifdef DEBUGGING
+#if defined(DEBUGGING) && !defined(USETHREADS)
=	ngmax[nextrcline-1] = tmpngmax;
=#endif
@@ -658,5 +661,5 @@
=	tmprcnums = rcnums[nextrcline-1];
=	tmpsoftptr = softptr[nextrcline-1];
-#ifdef DEBUGGING
+#if defined(DEBUGGING) && !defined(USETHREADS)
=	tmpngmax = ngmax[nextrcline-1];
=#endif
@@ -670,5 +673,5 @@
=	    rcnums[i+1] = rcnums[i];
=	    softptr[i+1] = softptr[i];
-#ifdef DEBUGGING
+#if defined(DEBUGGING) && !defined(USETHREADS)
=	    ngmax[i+1] = ngmax[i];
=#endif
@@ -682,5 +685,5 @@
=	rcnums[newng] = tmprcnums;
=	softptr[newng] = tmpsoftptr;
-#ifdef DEBUGGING
+#if defined(DEBUGGING) && !defined(USETHREADS)
=	ngmax[newng] = tmpngmax;
=#endif
Index: rn.c
@@ -10,8 +10,11 @@
=*/
=
-static char rnid[] = "@(#)$Header: rn.c,v 4.3.3.1 90/07/21 20:31:38 davison Trn $";
-static char patchlevel[] = "Trn v1.0 based on Rn patchlevel 47";
+static char rnid[] = "@(#)$Header: rn.c,v 4.3.3.2 90/08/20 16:48:19 davison Trn $";
+static char patchlevel[] = "Trn v1.0.1 based on Rn patchlevel 47";
=
=/* $Log:	rn.c,v $
+ * Revision 4.3.3.2  90/08/20  16:48:19  davison
+ * Changed unthreaded group's default action, version #, email address.
+ * 
= * Revision 4.3.3.1  90/07/21  20:31:38  davison
= * Initial Trn Release
@@ -204,7 +207,6 @@
=    reprompt_newsgroup:
=#ifdef USETHREADS
-		    dfltcmd = (use_threads && select_on
-			&& (ART_NUM)toread[ng] >= select_on ?
-			ThreadedGroup ? "+ynq" : "=ynq" : "ynq");
+		    dfltcmd = (ThreadedGroup && select_on
+			&& (ART_NUM)toread[ng] >= select_on ? "+ynq" : "ynq");
=#else
=		    dfltcmd = "ynq";
@@ -537,5 +539,5 @@
=		    printf("\n%s",rnid);
=		    printf("\n%s",patchlevel);
-		    printf("\nSend bugs to davison at drivax.UUCP (davison%%drivax at uunet.uu.net)\n") FLUSH;
+		    printf("\nSend bugs to davison at dri.com (...!uunet!drivax!davison)\n") FLUSH;
=		    goto reask_newsgroup;
=		default:
Index: rt-select.c
@@ -1,5 +1,8 @@
-/* $Header: rt-select.c,v 4.3.3.1 90/07/24 22:04:07 davison Trn $
+/* $Header: rt-select.c,v 4.3.3.2 90/08/20 18:32:33 davison Trn $
=**
=** $Log:	rt-select.c,v $
+** Revision 4.3.3.2  90/08/20  18:32:33  davison
+** Reset scan_all_roots while selecting.
+** 
=** Revision 4.3.3.1  90/07/24  22:04:07  davison
=** Initial Trn Release
@@ -31,6 +34,6 @@
=static char *display_mode = select_order;
=static ART_NUM article_count;
-static int author_line, mask = 1;
-static char first_two_chars[3] = { ' ', ' ', '\0' };
+static int author_line;
+static char first_two_chars[3] = { ' ', ' ', '\0' }, mask = 1;
=
=#define MAX_SEL 64
@@ -73,4 +76,5 @@
=  select_threads:
=    /* Setup for selecting articles to read or set unread */
+    scan_all_roots = FALSE;
=    if( unread_selector ) {
=	page_char = '>';
Index: rthreads.c
@@ -1,5 +1,8 @@
-/* $Header: rthreads.c,v 4.3.3.1 90/06/20 23:00:28 davison Trn $
+/* $Header: rthreads.c,v 4.3.3.2 90/08/20 16:58:14 davison Trn $
=**
=** $Log:	rthreads.c,v $
+** Revision 4.3.3.2  90/08/20  16:58:14  davison
+** Added message for missing/bad db.init file.
+** 
=** Revision 4.3.3.1  90/06/20  23:00:28  davison
=** Initial Trn Release
@@ -36,5 +39,9 @@
=    filename = filexp( "%X/db.init" );
=    if( (fp_in = fopen( filename, "r" )) != Nullfp ) {
-	if( fread( &mt_bmap, 1, sizeof (BMAP), fp_in ) == sizeof (BMAP) ) {
+	if( fread( &mt_bmap, 1, sizeof (BMAP), fp_in ) >= sizeof (BMAP)-1 ) {
+	    if( mt_bmap.version != DB_VERSION ) {
+		printf( "\nThread database is the wrong version -- ignoring it.\n" ) FLUSH;
+		use_threads = FALSE;
+	    }
=	    mybytemap( &my_bmap );
=	    for( i = 0; i < sizeof (LONG); i++ ) {
@@ -48,6 +55,11 @@
=		}
=	    }
+	} else {
+	    goto no_db_init;
=	}
=	fclose( fp_in );
+    } else {
+      no_db_init:
+	printf( "\ndb.init read failed -- assuming no byte-order translations.\n\n" ) FLUSH;
=    }
=}
Index: threads.c
@@ -1,5 +1,8 @@
-/* $Header: threads.c,v 4.3.3.1 90/07/21 20:33:23 davison Trn $
+/* $Header: threads.c,v 4.3.3.2 90/08/20 16:49:38 davison Trn $
=**
=** $Log:	threads.c,v $
+** Revision 4.3.3.2  90/08/20  16:49:38  davison
+** Enlarged path buffers to be more consistent.
+** 
=** Revision 4.3.3.1  90/07/21  20:33:23  davison
=** Initial Trn Release
@@ -23,7 +26,7 @@
={
=    register char *ptr;
-    static char name_buff[256];
+    static char name_buff[512];
=#ifndef LONG_THREAD_NAMES
-    char group_buff[256];
+    char group_buff[512];
=
=    strcpy( group_buff, group);
@@ -70,5 +73,5 @@
=	}
=	*--mp = j;
-	while (u.b[j] != 0) {
+	while( u.b[j] != 0 && u.w ) {
=	    u.w <<= 1;
=	}
@@ -95,5 +98,5 @@
=	}
=	*--mp = j;
-	while (u.b[j] != 0) {
+	while( u.b[j] != 0 && u.l ) {
=	    u.l <<= 1;
=	}
Index: threads.h
@@ -1,5 +1,8 @@
-/* $Header: threads.h,v 4.3.3.1 90/06/20 22:56:18 davison Trn $
+/* $Header: threads.h,v 4.3.3.2 90/08/20 16:50:09 davison Trn $
=**
=** $Log:	threads.h,v $
+** Revision 4.3.3.2  90/08/20  16:50:09  davison
+** Padded odd-boundaried arrays.  Upgraded database version #.
+** 
=** Revision 4.3.3.1  90/06/20  22:56:18  davison
=** Initial Trn Release
@@ -7,4 +10,6 @@
=*/
=
+#define DB_VERSION	2
+
=typedef char		BYTE;
=typedef short		WORD;
@@ -64,4 +69,5 @@
=    WORD thread_cnt;
=    WORD subject_cnt;
+    WORD pad_hack;
=} PACKED_ROOT;
=
@@ -85,4 +91,5 @@
=    WORD author;
=    WORD domain;
+    WORD pad_hack;
=} TOTAL;
=
@@ -91,3 +98,4 @@
=    BYTE w[sizeof (WORD)];
=    BYTE version;
+    BYTE pad_hack;
=} BMAP;
Index: trn.1
@@ -1,5 +1,8 @@
-''' $Header: trn.1,v 4.3.3.1 90/07/24 21:30:38 davison Trn $
+''' $Header: trn.1,v 4.3.3.2 90/08/20 16:50:51 davison Trn $
=''' 
=''' $Log:	trn.1,v $
+''' Revision 4.3.3.2  90/08/20  16:50:51  davison
+''' Changed email address.
+''' 
=''' Revision 4.3.3.1  90/07/24  21:30:38  davison
=''' Initial Trn Release
@@ -2186,5 +2189,5 @@
=and is now under the direction of Stan Barber <sob at bcm.tmc.edu>.
=.br
-Threaded version by Wayne Davison <davison%drivax at uunet.uu.net>
+Threaded version by Wayne Davison <davison at dri.com>
=.br
=(Mail all bug reports for trn to Wayne.)
Index: util.c
@@ -1,5 +1,8 @@
-/* $Header: util.c,v 4.3.3.1 90/07/21 20:34:10 davison Trn $
+/* $Header: util.c,v 4.3.3.2 90/08/20 16:51:44 davison Trn $
= *
= * $Log:	util.c,v $
+ * Revision 4.3.3.2  90/08/20  16:51:44  davison
+ * Fixed getcwd call to not overflow any buffers.
+ * 
= * Revision 4.3.3.1  90/07/21  20:34:10  davison
= * Initial Trn Release
@@ -262,5 +265,5 @@
=    char * name;
=	extern char * getcwd();
-    name = getcwd(np,1024);
+    name = getcwd(np,512);
=    return(name);
=}
SHAR_EOF
fi
exit 0
#	End of shell archive



More information about the Comp.sources.bugs mailing list