From: davison@borland.com (Wayne Davison)
Subject: Patch #3 for trn 2 (PART 2 of 2)
Organization: Borland International
Date: Wed, 30 Dec 1992 22:33:23 GMT

Here's the second part of the patch to generate trn 2.3.

..wayne..
---8<------8<------8<------8<---cut here--->8------>8------>8------>8---
Index:rn.c
Prereq: 2.2
@@ -1,3 +1,3 @@
-/*  trn -- threaded readnews program
+/*  trn -- threaded readnews program based on rn 4.4
  *
  *  Author/Maintainer of trn: davison@borland.com (Wayne Davison)
@@ -8,9 +8,14 @@
  *  Organization: System Development Corporation, Santa Monica
  *
- *  begun:   01/14/83
- *	1.0: 04/08/83
- *      2.0: 09/01/83
- *      RRN/RN: 11/01/89
- *      4.4  07/04/91
+ *  History:
+ *	01/14/83 - rn begun
+ *	04/08/83 - rn 1.0
+ *	09/01/83 - rn 2.0
+ *	05/01/85 - rn 4.3
+ *	11/01/89 - rn/rrn integration
+ *	11/25/89 - trn begun
+ *	07/21/90 - trn 1.0
+ *	07/04/91 - rn 4.4
+ *	11/25/91 - trn 2.0
  */
 /* This software is Copyright 1991 by Stan Barber. 
@@ -28,7 +33,13 @@
 
 static char rnid[] = "@(#)$Id: rn.c,v 4.4.3.1 1991/11/22 04:12:14 davison Trn $";
-static char patchlevel[] = "Trn 2.2 based on rn 4.4 pl 2";
+static char patchlevel[] = "Trn-2.3 based on rn-4.4PL4";
 
 /* $Log: rn.c,v $
+ * Revision 4.4.4.1  1992/02/23  21:25:39  sob
+ * Patch level 4
+ *
+ * Revision 4.4.3.1  1992/02/01  03:09:32  sob
+ * Release 4.4 Patchlevel 3
+ *
  * Revision 4.4.2.1  1991/12/01  18:05:42  sob
  * Patchlevel 2 changes
@@ -39,8 +50,4 @@
  * Revision 4.4  1991/09/09  20:27:37  sob
  * release 4.4
- *
- *
- *
- * 
  */
 
@@ -259,4 +266,5 @@
     do_command:
 		direction = 1;		/* default to forward motion */
+		addnewbydefault = 0;
 		switch (*buf) {
 		case 'P':		/* goto previous newsgroup */
@@ -361,8 +369,12 @@
 			strcpy(s,ngname);
 #endif
-		    if (isalpha(*s)) 
-			set_ngname(s);
-		    else {
-			if (isdigit(*s)) {
+		    if (isalnum(*s)) {
+		        char *_s;
+			for (_s=s; isdigit(*_s); _s++)
+			    ;
+		        if (*_s && !isspace(*_s))
+			    /* found non-digit before hitting end */
+			    set_ngname(s);
+			else {
 			    int rcnum;
 			    rcnum = atoi(s);
@@ -375,9 +387,9 @@
 			    }
 			}
-			else {
-			    printf("\nPlease specify a newsgroup.\n") FLUSH;
-			    goto reask_newsgroup;
-			}
 		    }
+		    else {
+			printf("\nPlease specify a newsgroup.\n") FLUSH;
+			goto reask_newsgroup;
+		    }
 #ifdef RELOCATE
 		    if (!get_ng(ngname,*buf=='m'))
@@ -405,36 +417,6 @@
 		case 'c':		/* catch up */
 #ifdef CATCHUP
-reask_catchup:
-#ifdef VERBOSE
-		    IF(verbose)
-			in_char("\nDo you really want to mark everything as read? [yn] ", 'C');
-		    ELSE
-#endif
-#ifdef TERSE
-			in_char("\nReally? [ynh] ", 'C');
-#endif
-		    setdef(buf,"y");
-#ifdef VERIFY
-		    printcmd();
-#endif
-		    putchar('\n') FLUSH;
-		    if (*buf == 'h') {
-#ifdef VERBOSE
-			printf("Type y or SP to mark all articles as read.\n");
-			printf("Type n to leave articles marked as they are.\n");
-#else
-			printf("y or SP to mark all read.\n");
-			printf("n to forget it.\n");
-#endif
-			goto reask_catchup;
-		    }
-		    else if (*buf != 'y' && *buf != 'n' && *buf != 'q') {
-			printf(hforhelp);
-			settle_down();
-			goto reask_catchup;
-		    } else if (*buf == 'y' && ng<nextrcline)
-			catch_up(ng);
-		    else
-			retry = TRUE;
+		    if (ng < nextrcline)
+			ask_catchup();
 		    ng++;
 #else
@@ -516,5 +498,4 @@
 		    goto reask_newsgroup;
 #else
-		    addnewbydefault = 0;
 		    /* FALL THROUGH */
 #endif
Index:mt-read.c
@@ -1,8 +1,3 @@
-/* $Id: mt-read.c,v 4.4.3.1 1991/11/22 04:12:15 davison Trn $
-**
-** $Log: mt-read.c,v $
-** Revision 4.4.3.1  1991/11/22  04:12:15  davison
-** Trn Release 2.0
-** 
+/* $Id: mt-read.c,v 2.3 1992/12/14 00:14:04 davison Trn $
 */
 
@@ -495,5 +490,5 @@
 		article = unk_domain.ids;
 		while (article) {
-		    safefree(article->id);
+		    safefree(&article->id);
 		    article = article->id_link;
 		}
@@ -503,5 +498,5 @@
 		    article = domain->ids;
 		    while (article) {
-			safefree(article->id);
+			safefree(&article->id);
 			article = article->id_link;
 		    }
Index:mt-write.c
@@ -1,8 +1,3 @@
-/* $Id: mt-write.c,v 4.4.3.1 1991/11/22 04:12:15 davison Trn $
-**
-** $Log: mt-write.c,v $
-** Revision 4.4.3.1  1991/11/22  04:12:15  davison
-** Trn Release 2.0
-** 
+/* $Id: mt-write.c,v 2.3 1992/12/14 00:14:05 davison Trn $
 */
 
Index:mthreads.8
@@ -1,3 +1,3 @@
-.\" $Id: mthreads.8,v 4.4.3.1 1991/11/22 04:13:39 davison Trn $
+.\" $Id: mthreads.8,v 2.3 1992/12/14 00:14:11 davison Trn $
 .\" 
 .de Sh
@@ -303,4 +303,6 @@
 .br
 $MTLIB/LOCKmthreads
+.br
+$MTLIB/LOCKmtdaemon
 .br
 Lots of thread data files.
Index:mthreads.c
@@ -1,8 +1,3 @@
-/* $Id: mthreads.c,v 4.4.3.1 1991/11/22 04:12:15 davison Trn $
-**
-** $Log: mthreads.c,v $
-** Revision 4.4.3.1  1991/11/22  04:12:15  davison
-** Trn Release 2.0
-** 
+/* $Id: mthreads.c,v 2.3 1992/12/14 00:14:06 davison Trn $
 */
 
@@ -28,11 +23,4 @@
 #include "mthreads.h"
 
-#ifdef TZSET
-#include <time.h>
-#else
-#include <sys/time.h>
-#include <sys/timeb.h>
-#endif
-
 #if !defined(FTRUNCATE) && !defined(CHSIZE)
 # ifdef F_FREESP
@@ -534,4 +522,5 @@
 {
     mt_unlock(locked);
+    (void) chdir(MTLIB);		/* for *mon.out files, etc. */
     exit(ret);
 }
Index:mthreads.h
@@ -1,8 +1,3 @@
-/* $Id: mthreads.h,v 4.4.3.1 1991/11/22 04:12:15 davison Trn $
-**
-** $Log: mthreads.h,v $
-** Revision 4.4.3.1  1991/11/22  04:12:15  davison
-** Trn Release 2.0
-** 
+/* $Id: mthreads.h,v 2.3 1992/12/14 00:14:07 davison Trn $
 */
 
Index:ndir.h.SH
@@ -8,10 +8,10 @@
  * running Configure.
  */
-/* $Id: ndir.h.SH,v 4.4 1991/09/09 20:23:31 sob Exp sob $
+/* $Id: ndir.h.SH,v 4.4 1991/09/09 20:23:31 sob Exp $
  *
  * $Log: ndir.h.SH,v $
-# Revision 4.4  1991/09/09  20:23:31  sob
-# release 4.4
-#
+ *Revision 4.4  1991/09/09  20:23:31  sob
+ *release 4.4
+ *
  *
  * 
Index:newsetup.1
@@ -1,5 +1,8 @@
-.\" $Id: newsetup.1,v 4.4.1.1 1991/09/25 19:36:48 sob Exp sob $
+.\" $Id: newsetup.1,v 4.4.3.1 1992/02/01 03:17:20 sob PATCH_3 sob $
 .\" 
 .\" $Log: newsetup.1,v $
+.\" Revision 4.4.3.1  1992/02/01  03:17:20  sob
+.\" Version 4.4 Patchlevel 3
+.\"
 .\" Revision 4.4.1.1  1991/09/25  19:36:48  sob
 .\" Changed quote macro to "standard" one
Index:newsetup.SH
@@ -6,7 +6,10 @@
 $startsh
 #
-# $Id: newsetup.SH,v 4.4.2.1 1991/12/01 18:05:42 sob PATCH_2 sob $
+# $Id: newsetup.SH,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
 # 
 # $Log: newsetup.SH,v $
+# Revision 4.4.3.1  1992/02/01  03:09:32  sob
+# Release 4.4 Patchlevel 3
+#
 # Revision 4.4.2.1  1991/12/01  18:05:42  sob
 # Fixed problems with CTRLA flag.
Index:newsgroups.1
@@ -1,5 +1,8 @@
-.\" $Id: newsgroups.1,v 4.4.1.1 1991/09/25 19:36:48 sob Exp sob $
+.\" $Id: newsgroups.1,v 4.4.3.1 1992/02/01 03:17:20 sob PATCH_3 sob $
 .\" 
 .\" $Log: newsgroups.1,v $
+.\" Revision 4.4.3.1  1992/02/01  03:17:20  sob
+.\" Version 4.4 Patchlevel 3
+.\"
 .\" Revision 4.4.1.1  1991/09/25  19:36:48  sob
 .\" Changed quote macro to "standard" one
Index:newsgroups.SH
@@ -5,7 +5,10 @@
 $spitshell >newsgroups <<!GROK!THIS!
 $startsh
-# $Id: newsgroups.SH,v 4.4.2.1 1991/12/01 18:05:42 sob PATCH_2 sob $
+# $Id: newsgroups.SH,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
 # 
 # $Log: newsgroups.SH,v $
+# Revision 4.4.3.1  1992/02/01  03:09:32  sob
+# Release 4.4 Patchlevel 3
+#
 # Revision 4.4.2.1  1991/12/01  18:05:42  sob
 # Patchlevel 2 changes
Index:ng.c
@@ -1,5 +1,8 @@
-/* $Id: ng.c,v 4.4 1991/09/09 20:23:31 sob Exp sob $
+/* $Id: ng.c,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
  *
  * $Log: ng.c,v $
+ * Revision 4.4.3.1  1992/02/01  03:09:32  sob
+ * Release 4.4 Patchlevel 3
+ *
  * Revision 4.4  1991/09/09  20:23:31  sob
  * release 4.4
@@ -143,4 +146,13 @@
     exit_code = NG_NORM;
 
+    if (extractdest) {
+	free(extractdest);
+	extractdest = Nullch;
+    }
+    if (extractprog) {
+	free(extractprog);
+	extractprog = Nullch;
+    }
+
 #ifdef SERVER
     sprintf(ser_line, "GROUP %s", ngname);
@@ -835,15 +847,19 @@
 #ifdef VERBOSE
 		    IF(verbose)
-			fprintf(stdout,"\n\
-There is no %s article prior to this one.\n",cp) FLUSH;
+			printf("\nThere is no %s article prior to this one.\n",
+				cp) FLUSH;
 		    ELSE
 #endif
 #ifdef TERSE
-			fprintf(stdout,"\nNo prior %s.\n",cp) FLUSH;
+			printf("\nNo prior %s.\n",cp) FLUSH;
 #endif
 		    return AS_ASK;
 		}
-		*buf = '{';
-		p_art--;
+		if (*buf == '{')
+		    p_art = p_articles + p_roots[p_art->root].articles;
+		else {
+		    *buf = '{';
+		    p_art--;
+		}
 	    }
 	    else
@@ -917,4 +933,31 @@
 	}
 	goto not_threaded;
+    case '(':			/* goto previous sibling */
+    case ')':			/* goto next sibling */
+	if (p_art) {
+	    PACKED_ARTICLE *ta;
+	    if (*buf == '(') {
+		ta = find_prev_sib();
+	    } else {
+		ta = find_next_sib();
+	    }
+	    if (!ta) {
+		register char *cp = (*buf == '(' ? "previous" : "next");
+#ifdef VERBOSE
+		IF(verbose)
+		    printf("\nThis article has no %s sibling.\n",cp) FLUSH;
+		ELSE
+#endif
+#ifdef TERSE
+		    printf("\nNo %s sibling.\n",cp) FLUSH;
+#endif
+		return AS_ASK;
+	    }
+	    p_art = ta;
+	    art = p_art->num;
+	    reread = TRUE;
+	    return AS_NORM;
+	}
+	goto not_threaded;
     case 'T':
 	if (p_art) {
@@ -938,5 +981,6 @@
 	goto normal_search;
     case ',':		/* kill this node and all descendants */
-	mark_as_read();
+	if (art >= absfirst && art <= lastart)
+	    mark_as_read();
 	*buf = 'K';
     case 'k':		/* kill current subject # (e.g. [1]) */
@@ -1232,5 +1276,5 @@
 	return AS_ASK;
     case 'm':
-	if (art <= lastart) {
+	if (art >= absfirst && art <= lastart) {
 	    unmark_as_read();
 	    printf("\nArticle %ld marked as still unread.\n",(long)art) FLUSH;
@@ -1238,58 +1282,8 @@
 	return AS_ASK;
     case 'c':			/* catch up */
-      reask_catchup:
-#ifdef VERBOSE
-	IF(verbose)
-	    in_char("\nDo you really want to mark everything as read? [yn] ",
-		'C');
-	ELSE
-#endif
-#ifdef TERSE
-	    in_char("\nReally? [ynh] ", 'C');
-#endif
-	setdef(buf,"y");
-#ifdef VERIFY
-	printcmd();
-#endif
-	putchar('\n') FLUSH;
-	if (*buf == 'h') {
-#ifdef VERBOSE
-	    IF(verbose)
-		fputs("\
-Type y or SP to mark all articles as read.\n\
-Type n to leave articles marked as they are.\n\
-Type u to mark everything read and unsubscribe.\n\
-",stdout) FLUSH;
-	    ELSE
-#endif
-#ifdef TERSE
-		fputs("\
-y or SP to mark all read.\n\
-n to forget it.\n\
-u to mark all and unsubscribe.\n\
-",stdout) FLUSH;
-#endif
-	    goto reask_catchup;
-	}
-	else if (*buf == 'n' || *buf == 'q') {
+	switch (ask_catchup()) {
+	case 'n':
 	    return AS_ASK;
-	}
-	else if (*buf != 'y' && *buf != 'u') {
-	    fputs(hforhelp,stdout) FLUSH;
-	    settle_down();
-	    goto reask_catchup;
-	}
-	for (i = firstart; i <= lastart; i++) {
-	    oneless(i);		/* mark as read */
-	}
-#ifdef USETHREADS
-	selected_count = selected_root_cnt = unthreaded = 0;
-#endif
-#ifdef DELAYMARK
-	if (dmfp)
-	    yankback();
-#endif
-	if (*buf == 'u') {
-	    rcchar[ng] = NEGCHAR;
+	case 'u':
 	    return AS_CLEAN;
 	}
@@ -1307,5 +1301,5 @@
     case 'j':
 	putchar('\n') FLUSH;
-	if (art <= lastart)
+	if (art >= absfirst && art <= lastart)
 	    mark_as_read();
 	return AS_ASK;
@@ -1504,4 +1498,5 @@
 	return AS_ASK;
     }
+    case 'Z':
     case 'z': {
 	supersede_article();	/* supersedes */
@@ -1599,3 +1594,87 @@
 	    dfltcmd = "npq";
     }
+}
+
+/* Ask the user about catching-up the current group.  Returns 'y' if yes,
+** 'n' or 'N' if no ('N' means we used one line when in the thread selector),
+** or 'u' for yes with unsubscribe.  Actually performs the catchup and
+** unsubscription as needed.
+*/
+char
+ask_catchup()
+{
+    bool use_one_line;
+
+    if (mode == 't')
+	use_one_line = TRUE;
+    else {
+	putchar('\n') FLUSH;
+	use_one_line = FALSE;
+    }
+reask_catchup:
+#ifdef VERBOSE
+    IF(verbose)
+	in_char("Do you really want to mark everything as read? [yn] ", 'C');
+    ELSE
+#endif
+#ifdef TERSE
+	in_char("Really? [ynh] ", 'C');
+#endif
+    setdef(buf,"y");
+#ifdef VERIFY
+    printcmd();
+#endif
+    if (*buf == 'h') {
+	use_one_line = FALSE;
+#ifdef VERBOSE
+	IF(verbose)
+	    fputs("\n\
+Type y or SP to mark all articles as read.\n\
+Type n to leave articles marked as they are.\n\
+Type u to mark everything read and unsubscribe.\n\n\
+",stdout) FLUSH;
+	ELSE
+#endif
+#ifdef TERSE
+	    fputs("\n\
+y or SP to mark all read.\n\
+n to forget it.\n\
+u to mark all and unsubscribe.\n\n\
+",stdout) FLUSH;
+#endif
+	goto reask_catchup;
+    }
+    if (*buf == 'n' || *buf == 'q') {
+	if (use_one_line)
+	    return 'N';
+	putchar('\n') FLUSH;
+	return 'n';
+    }
+    if (*buf != 'y' && *buf != 'u') {
+	use_one_line = FALSE;
+	printf("\n%s\n", hforhelp) FLUSH;
+	settle_down();
+	goto reask_catchup;
+    }
+    if (mode == 'n') {
+	putchar('\n') FLUSH;
+	catch_up(ng);
+    }
+    else {
+	int i;
+
+	for (i = firstart; i <= lastart; i++)
+	    oneless(i);		/* mark as read */
+#ifdef USETHREADS
+	selected_count = selected_root_cnt = unthreaded = 0;
+#endif
+#ifdef DELAYMARK
+	if (dmfp)
+	    yankback();
+#endif
+	putchar('\n') FLUSH;
+    }
+    if (*buf == 'u')
+	rcchar[ng] = NEGCHAR;
+    return *buf;
 }
Index:ng.h
@@ -53,2 +53,3 @@
 #endif
 void	setdfltcmd ANSI((void));
+char	ask_catchup ANSI((void));
Index:ngdata.c
@@ -1,5 +1,8 @@
-/* $Id: ngdata.c,v 4.4.2.1 1991/12/01 18:05:42 sob PATCH_2 sob $
+/* $Id: ngdata.c,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
  *
  * $Log: ngdata.c,v $
+ * Revision 4.4.3.1  1992/02/01  03:09:32  sob
+ * Release 4.4 Patchlevel 3
+ *
  * Revision 4.4.2.1  1991/12/01  18:05:42  sob
  * Patchlevel 2 changes
@@ -93,15 +96,5 @@
     }
 #else /* not SERVER */
-
-    cp = filexp(ACTIVE);
-    actfp = fopen(cp,"r");
-    if (actfp == Nullfp) {
-	printf(cantopen,cp) FLUSH;
-	finalize(1);
-    }
-    activeitems = 0;
-    /* count entries */
-    while(fgets(buf,LBUFLEN,actfp) != NULL)
-	activeitems++;
+    ngdatansrv_init();
 #endif
     if (fseek(actfp,0L,0) == -1) {	/* just get to the beginning */
@@ -198,55 +191,4 @@
 }
 
-ACT_POS
-findact(outbuf,nam,len,suggestion)
-char *outbuf;
-char *nam;
-int len;
-long suggestion;
-{
-    ACT_POS retval;
-
-    fseek(actfp,100000L,1);	/* hopefully this forces a reread */
-    if (suggestion == 0L || fseek(actfp,suggestion,0) < 0 ||
-      fgets(outbuf,80,actfp) == Nullch ||
-      outbuf[len] != ' ' ||
-      strnNE(outbuf,nam,len)) {
-#ifdef DEBUGGING
-	if (debug & DEB_SOFT_POINTERS)
-	    printf("Missed, looking for %s in %sLen = %d\n",nam,outbuf,len)
-	      FLUSH;
-#endif
-	fseek(actfp,0L,0);
-#ifndef lint
-	retval = (ACT_POS)ftell(actfp);
-#else
-	retval = Null(ACT_POS);
-#endif /* lint */
-	while (fgets(outbuf,80,actfp) != Nullch) {
-	    if (outbuf[len] == ' ' && strnEQ(outbuf,nam,len))
-		return retval;
-#ifndef lint
-	    retval = (ACT_POS) ftell(actfp);
-#endif /* lint */
-	    if (ferror(actfp)) {
-		perror("error on active file"); /* something is wrong */
-		sig_catcher(0);
-	    }
-	}
-	if(ferror(actfp)) {
-	    perror("error on active file");
-	    sig_catcher(0);
-	}
-	return (ACT_POS) -1;
-    }
-    else
-#ifndef lint
-	return (ACT_POS) suggestion;
-#else
-	return retval;
-#endif /* lint */
-    /*NOTREACHED*/
-}
-
 /* determine the absolutely first existing article number */
 #ifdef SERVER
@@ -355,5 +297,5 @@
     register DIR *dirp;
     register struct DIRTYPE *dp;
-    register ART_NUM min = 1000000;
+    register ART_NUM min = 0;
     register ART_NUM maybe;
     register char *p;
@@ -366,5 +308,5 @@
 	return 0;
     while ((dp = readdir(dirp)) != Null(struct DIRTYPE *)) {
-	if ((maybe = atol(dp->d_name)) < min && maybe > floor) {
+	if (((maybe = atol(dp->d_name)) < min || !min) && maybe > floor) {
 	    for (p = dp->d_name; *p; p++)
 		if (!isdigit(*p))
@@ -393,5 +335,5 @@
     }
     closedir(dirp);
-    return min==1000000 ? 0 : min;
+    return min;
 }
 #endif
Index:ngdata.h
@@ -1,5 +1,8 @@
-/* $Id: ngdata.h,v 4.4 1991/09/09 20:23:31 sob Exp sob $
+/* $Id: ngdata.h,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
  *
  * $Log: ngdata.h,v $
+ * Revision 4.4.3.1  1992/02/01  03:09:32  sob
+ * Release 4.4 Patchlevel 3
+ *
  * Revision 4.4  1991/09/09  20:23:31  sob
  * release 4.4
@@ -28,5 +31,5 @@
     EXT char active_name[MAXFILENAME];
     EXT time_t lastactfetch INIT(0);
-#define MINFETCHTIME (5 * 60)
+#define MINFETCHTIME (2 * 60 * 60)
 #endif
 
Index:nghash.c
@@ -0,0 +1,140 @@
+/* $Id: nghash.c,v 3.0 1992/02/01 03:09:32 davison Trn $
+ */
+/*
+ * This software is Copyright 1991 by Stan Barber.
+ *
+ * Permission is hereby granted to copy, reproduce, redistribute or otherwise
+ * use this software as long as: there is no monetary profit gained
+ * specifically from the use or reproduction of this software, it is not
+ * sold, rented, traded or otherwise marketed, and this copyright notice is
+ * included prominently in any copy made.
+ *
+ * The author make no claims as to the fitness or correctness of this software
+ * for any use whatsoever, and it is provided as is. Any use of this software
+ * is at the user's own risk.
+ */
+
+#include "EXTERN.h"
+#include "common.h"
+#include "ndir.h"
+#include "rcstuff.h"
+#include "rn.h"
+#include "intrp.h"
+#include "final.h"
+#include "rcln.h"
+#include "util.h"
+#ifdef SERVER
+#include "server.h"
+#endif
+#include "ngdata.h"
+
+#include <string.h>
+#include "hdbm.h"
+
+static HASHTABLE *acthash;
+static char *actfile;
+
+void
+ngdatansrv_init()		/* non-SERVER initialisation */
+{
+    register long offset = 0;
+    char *cp = filexp(ACTIVE);
+    struct stat actstat;
+
+    actfp = fopen(cp, "r");
+    if (actfp == Nullfp) {
+	printf(cantopen, cp) FLUSH;
+	finalize(1);
+    }
+
+    /* rn was being a slug about rereading the active file over and
+     * over; try using a really big buffer to keep it in core. */
+    (void) fstat(fileno(actfp), &actstat);
+    actfile = safemalloc(actstat.st_size + 1);
+    rewind(actfp);
+    /*
+     * NOTE: this won't work on machines with ints too small to hold
+     * the size of the active file.
+     */
+    if (fread(actfile, 1, (int)actstat.st_size, actfp) != actstat.st_size) {
+	fprintf(stderr, "active file not read\n");
+	actfile[0] = '\0';
+    }
+    rewind(actfp);
+    actfile[actstat.st_size] = '\0';
+
+    acthash = hdbmcreate((int)(actstat.st_size/40), (unsigned (*)())NULL);
+    if (acthash == NULL) {
+	fprintf(stderr, "can't hash %s\n", filexp(ACTIVE));
+	finalize(1);
+    }
+
+    /* count entries */
+    rewind(actfp);
+    for (activeitems = 0; fgets(buf, LBUFLEN, actfp) != NULL; activeitems++) {
+	register char *p = strchr(buf, ' ');
+	HDBMDATUM key, data;
+
+	/* key.dat_ptr must be allocated to make it permanent for hashstore */
+	if (p == NULL)
+	    p = buf;
+	data.dat_ptr = key.dat_ptr = actfile + offset;
+	key.dat_len = p - buf;
+	data.dat_len = strlen(buf);
+	if (!hdbmstore(acthash, key, data)) {
+	    fprintf(stderr, "can't install hash key %s\n", key.dat_ptr);
+	    finalize(1);
+	}
+	offset += data.dat_len;
+    }
+}
+
+ACT_POS
+findact(outbuf, nam, len, suggestion)
+register char *outbuf;
+register char *nam;
+register int len;
+register long suggestion;
+{
+    register ACT_POS retval;
+    extern int debug;
+
+    /* see if we know the right place and can just return */
+    if (suggestion != 0 && fseek(actfp, suggestion, 0) >= 0
+     && fgets(outbuf, 80, actfp) != NULL && outbuf[len] == ' '
+     && strnEQ(outbuf, nam, len))
+	return suggestion;
+
+    /* hmm, apparently not, gotta look it up. */
+    if (debug & DEB_SOFT_POINTERS)
+	printf("Missed, looking for %s in %sLen = %d\n",nam,outbuf,len) FLUSH;
+    /* can we just do a quick hashed lookup? */
+    if (acthash != NULL) {
+	HDBMDATUM key, data;
+
+	outbuf[0] = '\0';
+	key.dat_ptr = nam;
+	key.dat_len = len;
+	data = hdbmfetch(acthash, key);
+	if (data.dat_ptr == NULL)
+	    return -1;
+	else {
+	    (void) memcpy(outbuf, data.dat_ptr, (int)data.dat_len);
+	    outbuf[data.dat_len] = '\0';
+	    return data.dat_ptr - actfile;
+	}
+    }
+
+    /* apparently not.  gotta do it the slow way. */
+    (void) fseek(actfp, 0L, 0);
+    for (retval = 0; fgets(outbuf,80,actfp) != NULL; retval += strlen(outbuf))
+	if (outbuf[len] == ' ' && strnEQ(outbuf, nam, len))
+	    break;
+    if (ferror(actfp)) {
+	perror("error on active file");
+	sig_catcher(0);
+	/* NOTREACHED */
+    } else if (feof(actfp))
+	return -1;	/* no such group */
+    return retval;
+}
Index:ngsrch.c
@@ -1,5 +1,8 @@
-/* $Id: ngsrch.c,v 4.4 1991/09/09 20:23:31 sob Exp sob $
+/* $Id: ngsrch.c,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
  *
  * $Log: ngsrch.c,v $
+ * Revision 4.4.3.1  1992/02/01  03:09:32  sob
+ * Release 4.4 Patchlevel 3
+ *
  * Revision 4.4  1991/09/09  20:23:31  sob
  * release 4.4
Index:ngsrch.h
@@ -1,5 +1,8 @@
-/* $Id: ngsrch.h,v 4.4 1991/09/09 20:23:31 sob Exp sob $
+/* $Id: ngsrch.h,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
  *
  * $Log: ngsrch.h,v $
+ * Revision 4.4.3.1  1992/02/01  03:09:32  sob
+ * Release 4.4 Patchlevel 3
+ *
  * Revision 4.4  1991/09/09  20:23:31  sob
  * release 4.4
Index:nntp/xthread-11t.to.11t2
@@ -0,0 +1,233 @@
+This patch takes NNTP 1.5.11t up to my current release of 1.5.11t2.
+
+..wayne..
+
+Index:common/version.c
+Prereq: "1.5.11t
+@@ -3,3 +3,3 @@
+  */
+ 
+-char	nntp_version[] = "1.5.11t (16 November 1991)";
++char	nntp_version[] = "1.5.11t2 (14 December 1992)";
+Index:common/clientlib.c
+@@ -606,74 +606,4 @@
+ 
+ 
+-static	long	rawbytes = -1;	/* bytes remaining to be transfered */
+-
+-/*
+- * rawcheck_server -- get a line of text from the server, interpreting
+- * it as a status message for a raw (binary) command.  Call this once
+- * before calling rawget_server() for the actual data transfer.
+- *
+- *	Parameters:	"string" has the buffer space for the
+- *			line received.
+- *			"size" is the size of the buffer.
+- *
+- *	Returns:	-1 on error, otherwise the length of the raw data.
+- *
+- *	Side effects:	Talks to server, changes contents of "string".
+- */
+-long
+-rawcheck_server(string, size)
+-char	*string;
+-int	size;
+-{
+-	/* try to get the status line and the status code */
+-	if (get_server(string, size) || *string != CHAR_OK)
+-		return rawbytes = -1;
+-
+-	/* try to get the number of bytes being transfered */
+-	if (sscanf(string, "%*d%ld", &rawbytes) != 1)
+-		return rawbytes = -1;
+-	return rawbytes;
+-}
+-
+-
+-/*
+- * rawget_server -- read data from the server in raw format.  This call must
+- * follow an appropriate put_server command and a rawcheck_server call.
+- *
+- *	Parameters:	"buf" is the buffer for the data to receive.
+- *			"n" is the size of the buffer.
+- *
+- *	Returns:	0 on EOF, otherwise the length of the read.
+- *
+- *	Side effects:	Talks to server, changes contents of "buf".
+- */
+-long
+-rawget_server(buf, n)
+-void	*buf;
+-long	n;
+-{
+-	/* if no bytes to read, then just return EOF */
+-	if (rawbytes < 0)
+-		return 0;
+-
+-	/* try to read some data from the server */
+-	if (rawbytes) {
+-		n = fread(buf, 1, n > rawbytes ? rawbytes : n, ser_rd_fp);
+-		rawbytes -= n;
+-	} else
+-		n = 0;
+-
+-	/* if no more left, then fetch the end-of-command signature */
+-	if (!rawbytes)
+-	{
+-		char buf[5];	/* "\r\n.\r\n" */
+-
+-		fread(buf, 1, 5, ser_rd_fp);
+-		rawbytes = -1;
+-	}
+-	return n;
+-}
+-
+-
+ /*
+  * close_server -- close the connection to the server, after sending
+Index:common/clientlib.h
+@@ -9,5 +9,3 @@
+ extern	void	put_server();
+ extern	int	get_server();
+-extern	long	rawcheck_server();
+-extern	long	rawget_server();
+ extern	void	close_server();
+Index:server/group.c
+@@ -117,2 +117,63 @@
+ 	(void) fflush(stdout);
+ }
++
++#ifdef LISTGROUP
++/*
++ * LISTGROUP [group]
++ *
++ * Lists all article numbers (filenames) in the given group. Used by
++ * newsreaders such as nn and trn for fast validation of a database.
++ * If a group name is given it becomes the current group.
++ *
++ * This command is an extention, and not included in RFC 977.
++ */
++
++listgroup(argc, argv)
++	int		argc;
++	char		*argv[];
++{
++	register int i;
++
++	if (argc == 2) {
++		ingroup = 0;
++		/* This will output a success or failure message */
++		group(argc, argv);
++		if (!ingroup) {
++			return;
++		}
++	} else if (argc > 2) {
++		printf("%d Usage: LISTGROUP [newsgroup].\r\n", ERR_CMDSYN);
++		(void) fflush(stdout);
++		return;
++	} else if (!ingroup) {
++		printf("%d You are not currently in a newsgroup.\r\n",
++			ERR_NCING);
++		(void) fflush(stdout);
++		return;
++	} else if (!canread) {
++		printf("%d You only have permission to transfer, sorry.\r\n",
++			ERR_ACCESS);
++		(void) fflush(stdout);
++		return;
++	} else {
++		/* output a success message when no group name is given */
++		printf("%d %d %d %d (current group)\r\n",
++			OK_GROUP,
++			num_arts,
++			(num_arts > 0 ? art_array[0] : 0),
++			(num_arts > 0 ? art_array[num_arts-1] : 0));
++	}
++
++#ifdef LOG
++	syslog(LOG_INFO, "%s listgroup", hostname);
++#endif
++	for (i = 0; i < num_arts; i++) {
++		printf("%d\r\n", art_array[i]);
++	}
++	putchar('.');
++	putchar('\r');
++	putchar('\n');
++	(void) fflush(stdout);
++}
++
++#endif /* LISTGROUP */
+Index:server/help.c
+@@ -22,6 +22,9 @@
+ 	printf("STAT        NEWGROUPS    HELP\r\n");
+ 	printf("IHAVE       NEWNEWS      SLAVE\r\n");
+-#if defined(XHDR) || defined(XTHREAD)
+-	printf("\r\nAdditionally, the following extentions are supported:\r\n\r\n");
++#if defined(XHDR) || defined(XTHREAD) || defined(LISTGROUP)
++	printf("\r\nAdditionally, the following extensions are supported:\r\n\r\n");
++# ifdef LISTGROUP
++	printf("LISTGROUP   Retrieve a list of valid article-numbers.\r\n");
++# endif LISTGROUP
+ # ifdef	XHDR
+ 	printf("XHDR        Retrieve a single header line from a range of articles.\r\n");
+Index:server/newgroups.c
+@@ -24,4 +24,5 @@
+ 	long		date;
+ 	register FILE	*date_fp;
++	char		*reqlist[2];
+ 
+ 	if (argc < 3) {
+@@ -97,4 +98,20 @@
+ 
+ 		if (distcount == 0) {
++#ifdef ACTIVE_TIMES_FILE
++			reqlist[0] = line;
++#else
++			reqlist[0] = cp + 1;
++#endif
++			reqlist[1] = NULL;
++
++			if (ngpermcount) {
++			    if (ngmatch(s1strneql, ALLBUT,
++			        ngpermlist, ngpermcount, reqlist, 1) == 0) {
++			         continue;
++			    }
++			} else if (ALLBUT == 0) {
++			    continue;
++			}
++
+ #ifdef ACTIVE_TIMES_FILE
+ 			putline(line);
+Index:server/serve.c
+@@ -27,5 +27,5 @@
+ extern	int	ahbs(), group(), help(), ihave();
+ extern	int	list(), newgroups(), newnews(), nextlast(), post();
+-extern	int	slave(), stat(), xhdr(), xthread();
++extern	int	slave(), stat(), listgroup(), xhdr(), xthread();
+ 
+ extern int errno;
+@@ -53,4 +53,7 @@
+ 	"last",		0,	nextlast,
+ 	"list",		0,	list,
++#ifdef LISTGROUP
++	"listgroup",	0,	listgroup,
++#endif LISTGROUP
+ 	"newgroups",	0,	newgroups,
+ 	"newnews",	0,	newnews,
+Index:server/xthread.c
+@@ -131,5 +131,5 @@
+ {
+ 	static char name_buff[MAXPATHLEN];
+-#ifndef LONG_THREAD_NAMES
++#ifdef LONG_THREAD_NAMES
+ 	char group_buff[512];
+ 	register char *ptr;
+@@ -137,6 +137,6 @@
+ 	strcpy(group_buff, group);
+ 	ptr = group = group_buff;
+-	while ((ptr = index(ptr, '.'))) {
+-		*ptr = '/';
++	while ((ptr = index(ptr, '/'))) {
++		*ptr = '.';
+ 	}
+ #endif
Index:nntp/xthread.patch
@@ -29,10 +29,8 @@
 
 Tim can be contacted at:  iverson@xstor.com -/- uunet!xstor!iverson
--- 
- \  /| / /|\/ /| /(_)     Wayne Davison
-(_)/ |/ /\|/ / |/  \      davison@borland.com
-   (W   A  Y   N   e)
 
-Index: common/version.c
+..wayne..
+
+Index:common/version.c
 Prereq: "1.5.11
 @@ -3,3 +3,3 @@
@@ -40,93 +38,6 @@
  
 -char	nntp_version[] = "1.5.11 (10 February 1991)";
-+char	nntp_version[] = "1.5.11t (16 November 1991)";
-Index: common/clientlib.c
-@@ -606,4 +606,74 @@
- 
- 
-+static	long	rawbytes = -1;	/* bytes remaining to be transfered */
-+
-+/*
-+ * rawcheck_server -- get a line of text from the server, interpreting
-+ * it as a status message for a raw (binary) command.  Call this once
-+ * before calling rawget_server() for the actual data transfer.
-+ *
-+ *	Parameters:	"string" has the buffer space for the
-+ *			line received.
-+ *			"size" is the size of the buffer.
-+ *
-+ *	Returns:	-1 on error, otherwise the length of the raw data.
-+ *
-+ *	Side effects:	Talks to server, changes contents of "string".
-+ */
-+long
-+rawcheck_server(string, size)
-+char	*string;
-+int	size;
-+{
-+	/* try to get the status line and the status code */
-+	if (get_server(string, size) || *string != CHAR_OK)
-+		return rawbytes = -1;
-+
-+	/* try to get the number of bytes being transfered */
-+	if (sscanf(string, "%*d%ld", &rawbytes) != 1)
-+		return rawbytes = -1;
-+	return rawbytes;
-+}
-+
-+
-+/*
-+ * rawget_server -- read data from the server in raw format.  This call must
-+ * follow an appropriate put_server command and a rawcheck_server call.
-+ *
-+ *	Parameters:	"buf" is the buffer for the data to receive.
-+ *			"n" is the size of the buffer.
-+ *
-+ *	Returns:	0 on EOF, otherwise the length of the read.
-+ *
-+ *	Side effects:	Talks to server, changes contents of "buf".
-+ */
-+long
-+rawget_server(buf, n)
-+void	*buf;
-+long	n;
-+{
-+	/* if no bytes to read, then just return EOF */
-+	if (rawbytes < 0)
-+		return 0;
-+
-+	/* try to read some data from the server */
-+	if (rawbytes) {
-+		n = fread(buf, 1, n > rawbytes ? rawbytes : n, ser_rd_fp);
-+		rawbytes -= n;
-+	} else
-+		n = 0;
-+
-+	/* if no more left, then fetch the end-of-command signature */
-+	if (!rawbytes)
-+	{
-+		char buf[5];	/* "\r\n.\r\n" */
-+
-+		fread(buf, 1, 5, ser_rd_fp);
-+		rawbytes = -1;
-+	}
-+	return n;
-+}
-+
-+
- /*
-  * close_server -- close the connection to the server, after sending
-@@ -633,3 +703,2 @@
- 	(void) fclose(ser_rd_fp);
- }
--
-Index: common/clientlib.h
-@@ -9,3 +9,5 @@
- extern	void	put_server();
- extern	int	get_server();
-+extern	long	rawcheck_server();
-+extern	long	rawget_server();
- extern	void	close_server();
-Index: common/conf.h.dist
++char	nntp_version[] = "1.5.11t2 (14 December 1992)";
+Index:common/conf.h.dist
 @@ -95,4 +95,19 @@
  			/* loaded already, defining this may be a bad idea */
@@ -172,5 +83,5 @@
  #endif
  
-Index: common/nntp.h
+Index:common/nntp.h
 @@ -49,4 +49,5 @@
  #define	OK_AUTHSYS	280	/* Authorization system ok */
@@ -179,5 +90,5 @@
  
  #define	CONT_XFER	335	/* Continue to send article */
-Index: server/Makefile
+Index:server/Makefile
 @@ -7,5 +7,5 @@
  	newgroups.o newnews.o nextlast.o ngmatch.o post.o parsit.o scandir.o \
@@ -194,5 +105,5 @@
  
  SRVRINC = common.h ../common/conf.h ../common/nntp.h timer.h
-Index: server/common.h
+Index:server/common.h
 @@ -164,4 +164,9 @@
  extern	char	inews[];
@@ -205,5 +116,5 @@
  
  extern	char	**group_array;
-Index: server/globals.c
+Index:server/globals.c
 @@ -27,4 +27,9 @@
  char	rnews[] = RNEWS;
@@ -216,5 +127,5 @@
  /*
   * Other random externals.
-Index: server/group.c
+Index:server/group.c
 @@ -5,4 +5,8 @@
  #include "common.h"
@@ -226,20 +137,87 @@
  /*
   * GROUP newsgroup
-@@ -97,4 +101,8 @@
- 
+@@ -98,4 +102,8 @@
  	ingroup = 1;
-+
+ 
 +#ifdef	XTHREAD
 +	threadfile = thread_name(argv[1]);
 +#endif
- 
++
  	while ((cp = index(argv[1], '/')) != (char *) NULL)
-Index: server/help.c
-@@ -22,6 +22,13 @@
+ 		*cp = '.';
+@@ -109,2 +117,63 @@
+ 	(void) fflush(stdout);
+ }
++
++#ifdef LISTGROUP
++/*
++ * LISTGROUP [group]
++ *
++ * Lists all article numbers (filenames) in the given group. Used by
++ * newsreaders such as nn and trn for fast validation of a database.
++ * If a group name is given it becomes the current group.
++ *
++ * This command is an extention, and not included in RFC 977.
++ */
++
++listgroup(argc, argv)
++	int		argc;
++	char		*argv[];
++{
++	register int i;
++
++	if (argc == 2) {
++		ingroup = 0;
++		/* This will output a success or failure message */
++		group(argc, argv);
++		if (!ingroup) {
++			return;
++		}
++	} else if (argc > 2) {
++		printf("%d Usage: LISTGROUP [newsgroup].\r\n", ERR_CMDSYN);
++		(void) fflush(stdout);
++		return;
++	} else if (!ingroup) {
++		printf("%d You are not currently in a newsgroup.\r\n",
++			ERR_NCING);
++		(void) fflush(stdout);
++		return;
++	} else if (!canread) {
++		printf("%d You only have permission to transfer, sorry.\r\n",
++			ERR_ACCESS);
++		(void) fflush(stdout);
++		return;
++	} else {
++		/* output a success message when no group name is given */
++		printf("%d %d %d %d (current group)\r\n",
++			OK_GROUP,
++			num_arts,
++			(num_arts > 0 ? art_array[0] : 0),
++			(num_arts > 0 ? art_array[num_arts-1] : 0));
++	}
++
++#ifdef LOG
++	syslog(LOG_INFO, "%s listgroup", hostname);
++#endif
++	for (i = 0; i < num_arts; i++) {
++		printf("%d\r\n", art_array[i]);
++	}
++	putchar('.');
++	putchar('\r');
++	putchar('\n');
++	(void) fflush(stdout);
++}
++
++#endif /* LISTGROUP */
+Index:server/help.c
+@@ -22,6 +22,16 @@
  	printf("STAT        NEWGROUPS    HELP\r\n");
  	printf("IHAVE       NEWNEWS      SLAVE\r\n");
 -	printf("\r\nAdditionally, the following extention is supported:\r\n\r\n");
-+#if defined(XHDR) || defined(XTHREAD)
-+	printf("\r\nAdditionally, the following extentions are supported:\r\n\r\n");
++#if defined(XHDR) || defined(XTHREAD) || defined(LISTGROUP)
++	printf("\r\nAdditionally, the following extensions are supported:\r\n\r\n");
++# ifdef LISTGROUP
++	printf("LISTGROUP   Retrieve a list of valid article-numbers.\r\n");
++# endif LISTGROUP
 +# ifdef	XHDR
  	printf("XHDR        Retrieve a single header line from a range of articles.\r\n");
@@ -251,5 +229,33 @@
  	printf("\r\n");
  	printf("Bugs to Stan Barber (Internet: nntp@tmc.edu; UUCP: ...!bcm!nntp)\r\n");
-Index: server/serve.c
+Index:server/newgroups.c
+@@ -24,4 +24,5 @@
+ 	long		date;
+ 	register FILE	*date_fp;
++	char		*reqlist[2];
+ 
+ 	if (argc < 3) {
+@@ -97,4 +98,20 @@
+ 
+ 		if (distcount == 0) {
++#ifdef ACTIVE_TIMES_FILE
++			reqlist[0] = line;
++#else
++			reqlist[0] = cp + 1;
++#endif
++			reqlist[1] = NULL;
++
++			if (ngpermcount) {
++			    if (ngmatch(s1strneql, ALLBUT,
++			        ngpermlist, ngpermcount, reqlist, 1) == 0) {
++			         continue;
++			    }
++			} else if (ALLBUT == 0) {
++			    continue;
++			}
++
+ #ifdef ACTIVE_TIMES_FILE
+ 			putline(line);
+Index:server/serve.c
 @@ -27,5 +27,5 @@
  extern	int	ahbs(), group(), help(), ihave();
@@ -256,8 +262,16 @@
  extern	int	list(), newgroups(), newnews(), nextlast(), post();
 -extern	int	slave(), stat(), xhdr();
-+extern	int	slave(), stat(), xhdr(), xthread();
++extern	int	slave(), stat(), listgroup(), xhdr(), xthread();
  
  extern int errno;
-@@ -62,4 +62,7 @@
+@@ -53,4 +53,7 @@
+ 	"last",		0,	nextlast,
+ 	"list",		0,	list,
++#ifdef LISTGROUP
++	"listgroup",	0,	listgroup,
++#endif LISTGROUP
+ 	"newgroups",	0,	newgroups,
+ 	"newnews",	0,	newnews,
+@@ -62,4 +65,7 @@
  	"xhdr",		0,	xhdr,
  #endif XHDR
@@ -267,5 +281,5 @@
  };
  #define NUMCMDS (sizeof(cmdtbl) / sizeof(struct cmdent))
-Index: server/xthread.c
+Index:server/xthread.c
 @@ -0,0 +1,152 @@
 +/* This file (and only this file - not the entire nntp distribution) is
@@ -401,5 +415,5 @@
 +{
 +	static char name_buff[MAXPATHLEN];
-+#ifndef LONG_THREAD_NAMES
++#ifdef LONG_THREAD_NAMES
 +	char group_buff[512];
 +	register char *ptr;
@@ -407,6 +421,6 @@
 +	strcpy(group_buff, group);
 +	ptr = group = group_buff;
-+	while ((ptr = index(ptr, '.'))) {
-+		*ptr = '/';
++	while ((ptr = index(ptr, '/'))) {
++		*ptr = '.';
 +	}
 +#endif
Index:rcln.c
@@ -1,5 +1,8 @@
-/* $Id: rcln.c,v 4.4.2.1 1991/12/01 18:05:42 sob PATCH_2 sob $
+/* $Id: rcln.c,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
  *
  * $Log: rcln.c,v $
+ * Revision 4.4.3.1  1992/02/01  03:09:32  sob
+ * Release 4.4 Patchlevel 3
+ *
  * Revision 4.4.2.1  1991/12/01  18:05:42  sob
  * Patchlevel 2 changes
Index:rcln.h
@@ -1,5 +1,8 @@
-/* $Id: rcln.h,v 4.4 1991/09/09 20:27:37 sob Exp sob $
+/* $Id: rcln.h,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
  *
  * $Log: rcln.h,v $
+ * Revision 4.4.3.1  1992/02/01  03:09:32  sob
+ * Release 4.4 Patchlevel 3
+ *
  * Revision 4.4  1991/09/09  20:27:37  sob
  * release 4.4
Index:rcstuff.c
@@ -1,5 +1,8 @@
-/* $Id: rcstuff.c,v 4.4.2.1 1991/12/01 18:05:42 sob PATCH_2 sob $
+/* $Id: rcstuff.c,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
  *
  * $Log: rcstuff.c,v $
+ * Revision 4.4.3.1  1992/02/01  03:09:32  sob
+ * Release 4.4 Patchlevel 3
+ *
  * Revision 4.4.2.1  1991/12/01  18:05:42  sob
  * Patchlevel 2 changes
Index:rcstuff.h
@@ -1,5 +1,8 @@
-/* $Id: rcstuff.h,v 4.4.2.1 1991/12/01 18:05:42 sob PATCH_2 sob $
+/* $Id: rcstuff.h,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
  *
  * $Log: rcstuff.h,v $
+ * Revision 4.4.3.1  1992/02/01  03:09:32  sob
+ * Release 4.4 Patchlevel 3
+ *
  * Revision 4.4.2.1  1991/12/01  18:05:42  sob
  * Patchlevel 2 changes
Index:respond.c
@@ -1,5 +1,8 @@
-/* $Id: respond.c,v 4.4.2.1 1991/12/01 18:05:42 sob PATCH_2 sob $
+/* $Id: respond.c,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
  *
  * $Log: respond.c,v $
+ * Revision 4.4.3.1  1992/02/01  03:09:32  sob
+ * Release 4.4 Patchlevel 3
+ *
  * Revision 4.4.2.1  1991/12/01  18:05:42  sob
  * Patchlevel 2 changes
@@ -314,5 +317,5 @@
 	safecpy(altbuf,filexp(s),sizeof altbuf);
 	s = altbuf;
-	if (! index(s,'/')) {
+	if (*s != '/') {
 	    interp(buf, (sizeof buf), getval("SAVEDIR",SAVEDIR));
 	    if (makedir(buf,MD_DIR))	/* ensure directory exists */
@@ -531,4 +534,5 @@
     int myuid = getuid();
     int r = -1;
+    bool incl_body = (*buf == 'Z');
 
     if (artopen(art) == Nullfp) {
@@ -578,4 +582,13 @@
 	interp(buf, (sizeof buf), getval("SUPERSEDEHEADER",SUPERSEDEHEADER));
 	fputs(buf,tmpfp);
+	if (incl_body && artfp != Nullfp) {
+#ifdef ASYNC_PARSE
+	    parse_maybe(art);
+#endif
+	    fseek(artfp,(long)htype[PAST_HEADER].ht_minpos,0);
+	    while (fgets(buf,LBUFLEN,artfp) != Nullch) {
+		fputs(buf,tmpfp);
+	    }
+	}
 	fclose(tmpfp);
     	safecpy(cmd_buf,filexp(getval("NEWSPOSTER",NEWSPOSTER)),
Index:respond.h
@@ -1,5 +1,8 @@
-/* $Id: respond.h,v 4.4.2.1 1991/12/01 18:05:42 sob PATCH_2 sob $
+/* $Id: respond.h,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
  *
  * $Log: respond.h,v $
+ * Revision 4.4.3.1  1992/02/01  03:09:32  sob
+ * Release 4.4 Patchlevel 3
+ *
  * Revision 4.4.2.1  1991/12/01  18:05:42  sob
  * Patchlevel 2 changes
Index:rt-rn.c
@@ -1,8 +1,3 @@
-/* $Id: rt-rn.c,v 4.4.3.1 1991/11/22 04:12:18 davison Trn $
-**
-** $Log: rt-rn.c,v $
-** Revision 4.4.3.1  1991/11/22  04:12:18  davison
-** Trn Release 2.0
-** 
+/* $Id: rt-rn.c,v 2.3 1992/12/14 00:14:00 davison Trn $
 */
 
@@ -26,4 +21,5 @@
 
 static void find_depth(), cache_tree(), display_tree();
+static PACKED_ARTICLE *first_sib(), *last_sib();
 static char letter();
 
@@ -340,4 +336,7 @@
 		header_indent = ++cp - line;
 		line = cp;
+		if (!*line) {
+		    *--line = ' ';
+		}
 	    }
 	    i = 0;
@@ -664,5 +663,4 @@
 **   u - mark entire thread as "unread".
 **   U - mark this article and its descendants as "unread".
-**   x - go through the unread articles and just chase their xrefs.
 **   f - follow the thread (like 'n'), but don't attempt to find a new thread
 **	 if we run off the end.
@@ -676,9 +674,6 @@
     bool subthread_flag, chase_flag;
 
-    reread = FALSE;
+    reread = (cmd == 'N');
 
-    if (cmd == 'N') {
-	reread = TRUE;
-    }
     if (!p_art) {
 	if (ThreadedGroup && art > lastart) {
@@ -705,5 +700,5 @@
 
     /* Some commands encompass the entire thread */
-    if (cmd == 'k' || cmd == 'j' || cmd == 'J' || cmd == 'u' || cmd == 'x') {
+    if (cmd == 'k' || cmd == 'j' || cmd == 'J' || cmd == 'u') {
 	p_art = p_articles + p_roots[p_art->root].articles;
 	art = p_art->num;
@@ -727,12 +722,4 @@
 	scan_all_roots = FALSE;
     }
-    if (cmd == 'x') {
-	if (olden_days) {
-	    return;
-	}
-	if ((p_art->flags & HAS_XREFS) && !was_read(art)) {
-	    chase_xrefs(art, TRUE);
-	}
-    }
   follow_again:
     selected = (selected_roots[p_art->root] & 1);
@@ -739,5 +726,9 @@
     root_limit = upper_limit(p_art, subthread_flag);
     for (;;) {
-	if (++p_art == root_limit) {
+	if (Ctl(cmd) == Ctl('n') || cmd == 'f')
+	    next_art();
+	else
+	    p_art++;
+	if (p_art == root_limit) {
 	    break;
 	}
@@ -752,8 +743,4 @@
 	} else if (cmd == 'U') {
 	    set_unread(art, selected);
-	} else if (cmd == 'x') {
-	    if ((p_art->flags & HAS_XREFS) && !was_read(art)) {
-		chase_xrefs(art, TRUE);
-	    }
 	} else if (!was_read(art)
 		&& (curr_subj < 0 || curr_subj == p_art->subject)) {
@@ -815,4 +802,40 @@
 }
 
+/* Bump p_art to the next article.  Honors the breadth_first flag.
+*/
+void
+next_art()
+{
+    if (breadth_first) {
+	for (;;) {
+	    if (p_art->siblings) {
+		p_art += p_art->siblings;
+		return;					/* RETURN */
+	    }
+	    if (p_art->parent) {
+		p_art += p_art->parent + 1;
+	    } else {
+		p_art = p_articles + p_roots[p_art->root].articles;
+	    }
+	    for (;;) {
+		if (p_art->child_cnt) {
+		    p_art++;
+		    return;				/* RETURN */
+		}
+		while (!p_art->siblings) {
+		    if (!p_art->parent) {
+			p_art = upper_limit(p_art, FALSE);
+			return;				/* RETURN */
+		    }
+		    p_art += p_art->parent;
+		}
+		p_art += p_art->siblings;
+	    }/* for */
+	}/* for */
+    } else {
+	p_art++;
+    }
+}
+
 /* Go backward in the article tree.  Options match commands in article mode:
 **    p - previous unread article.
@@ -986,4 +1009,114 @@
     return p_articles + (artp->root == total.root-1 ?
 	total.article : p_roots[artp->root+1].articles);
+}
+
+/* Find the next "sibling" of this article, including cousins that are
+** the same distance from the root as we are.
+*/
+PACKED_ARTICLE *
+find_next_sib()
+{
+    PACKED_ARTICLE *ta, *tb;
+    int ascent;
+
+    ascent = 0;
+    ta = p_art;
+    for (;;) {
+	while (ta->siblings) {
+	    ta += ta->siblings;
+	    if (tb = first_sib(ta, ascent)) {
+		return tb;
+	    }
+	}
+	if (!ta->parent) {
+	    break;
+	}
+	ta += ta->parent;
+	ascent++;
+    }
+    return Nullart;
+}
+
+/* A recursive routine to find the first node at the proper depth.  This
+** article is at depth 0.
+*/
+static PACKED_ARTICLE *
+first_sib(ta, depth)
+PACKED_ARTICLE *ta;
+int depth;
+{
+    PACKED_ARTICLE *tb;
+
+    if (!depth) {
+	return ta;
+    }
+    for (;;) {
+	if (ta->child_cnt && (tb = first_sib(ta+1, depth-1))) {
+	    return tb;
+	}
+	if (!ta->siblings) {
+	    return Nullart;
+	}
+	ta += ta->siblings;
+    }
+}
+
+/* Find the previous "sibling" of this article, including cousins that are
+** the same distance from the root as we are.
+*/
+PACKED_ARTICLE *
+find_prev_sib()
+{
+    PACKED_ARTICLE *ta, *tb;
+    int i, ascent;
+
+    ascent = 0;
+    ta = p_art;
+    for (;;) {
+	tb = ta;
+	if (ta->parent) {
+	    ta += ta->parent + 1;
+	} else {
+	    ta = p_articles + p_roots[ta->root].articles;
+	}
+	if (tb = last_sib(ta, ascent, tb)) {
+	    return tb;
+	}
+	if (!ta->parent) {
+	    break;
+	}
+	ta += ta->parent;
+	ascent++;
+    }
+    return Nullart;
+}
+
+/* A recursive routine to find the last node at the proper depth.  This
+** article is at depth 0.
+*/
+static PACKED_ARTICLE *
+last_sib(ta, depth, limit)
+PACKED_ARTICLE *ta;
+int depth;
+PACKED_ARTICLE *limit;
+{
+    PACKED_ARTICLE *tb, *tc;
+
+    if (ta == limit) {
+	return Nullart;
+    }
+    if (ta->siblings) {
+	tc = ta+ta->siblings;
+	if (tc != limit && (tb = last_sib(tc,depth,limit))) {
+	    return tb;
+	}
+    }
+    if (!depth) {
+	return ta;
+    }
+    if (ta->child_cnt) {
+	return last_sib(ta+1, depth-1, limit);
+    }
+    return Nullart;
 }
 
Index:rt-select.c
@@ -1,8 +1,3 @@
-/* $Id: rt-select.c,v 4.4.3.1 1991/11/22 04:12:18 davison Trn $
-**
-** $Log: rt-select.c,v $
-** Revision 4.4.3.1  1991/11/22  04:12:18  davison
-** Trn Release 2.0
-** 
+/* $Id: rt-select.c,v 2.3 1992/12/14 00:14:12 davison Trn $
 */
 
@@ -426,6 +421,22 @@
 		    putchar('\n');
 		}
-		printf("Type ? for help.");
-		settle_down();
+		if (ch == 'c') {
+		    if ((ch = ask_catchup()) == 'y' || ch == 'u') {
+			ch = 'q';
+			break;
+		    }
+		    if (ch != 'N') {
+			ch = Ctl('l');
+			break;
+		    }
+		    if (can_home) {
+			carriage_return();
+			erase_eol();
+		    }
+		    printf("Aborted.");
+		} else {
+		    printf("Type ? for help.");
+		    settle_down();
+		}
 		displayed_status = TRUE;
 
@@ -499,5 +510,4 @@
 			    p_art = p_articles + p_roots[r].articles;
 			    art = 0;
-			    follow_thread('x');
 			}
 			/* FALL THROUGH */
@@ -585,5 +595,5 @@
 				p_art = p_articles + p_roots[j].articles;
 				art = 0;
-				follow_thread('j');
+				follow_thread('J');
 			    }
 			}
@@ -617,6 +627,11 @@
 
 		running_total = 0;
+		last_running = 0;
 		if (article_count) {
 		    for (j = 0; j < page_root; j++) {
+			last_running += root_article_cnts[j];
+		    }
+		    running_total = last_running;
+		    for ( ; j < i; j++) {
 			running_total += root_article_cnts[j];
 		    }
@@ -680,5 +695,5 @@
 		    p_art = p_articles + p_roots[j].articles;
 		    art = 0;
-		    follow_thread((selected_roots[j] & 4) ? 'j' : 'J');
+		    follow_thread('J');
 		}
 	    }
@@ -693,6 +708,4 @@
 		cur_root = 0;
 	    } else {
-		if (!output_chase_phrase)
-		    ch = 'o';
 		break;
 	    }
@@ -737,13 +750,12 @@
 	    if (!selected_root_cnt) {
 	      register r = root_hold[cur_root];
-		selected_roots[r] = mask;
-		selected_root_cnt++;
-		selected_count += root_article_cnts[r];
+		if (unread_selector || !(selected_roots[r] & 4)) {
+		    selected_roots[r] = mask;
+		    selected_root_cnt++;
+		    selected_count += root_article_cnts[r];
+		}
 	    }
 	}
     } while ((ch == '>' && i < max_root) || ch == '<');
-    if (ch != 'o') {
-	putchar('\n') FLUSH;
-    }
 
     if (unread_selector) {
@@ -771,7 +783,10 @@
 		p_art = p_articles + p_roots[j].articles;
 		art = 0;
-		follow_thread('j');
+		follow_thread('J');
 	    }
 	}
+    }
+    if (!output_chase_phrase) {
+	putchar('\n') FLUSH;
     }
     if (ch == 'U') {
Index:rthreads.c
@@ -1,8 +1,3 @@
-/* $Id: rthreads.c,v 4.4.3.1 1991/11/22 04:12:18 davison Trn $
-**
-** $Log: rthreads.c,v $
-** Revision 4.4.3.1  1991/11/22  04:12:18  davison
-** Trn Release 2.0
-** 
+/* $Id: rthreads.c,v 2.3 1992/12/14 00:14:13 davison Trn $
 */
 
@@ -59,5 +54,5 @@
 # endif
     put_server(ser_line);
-    rawcheck_server(ser_line, sizeof ser_line);
+    size = rawcheck_server(ser_line, sizeof ser_line);
 # ifdef DEBUGGING
     if (debug & DEB_NNTP) {
@@ -65,5 +60,10 @@
     }
 # endif
-    size = rawget_server((char*)&mt_bmap, sizeof (BMAP));
+    if (size < 0) {
+	printf("\nYour NNTP server isn't XTHREAD-compliant.\n") FLUSH;
+	use_threads = FALSE;
+	return;
+    }
+    size = rawget_server((char*)&mt_bmap, (long)sizeof (BMAP));
     if (size >= sizeof (BMAP) - 1) {
 #else /* !XTHREAD */
@@ -91,5 +91,5 @@
     }
 #ifdef XTHREAD
-    while (rawget_server(ser_line, sizeof ser_line)) {
+    while (rawget_server(ser_line, (long)sizeof ser_line)) {
 	;		/* trash any extraneous bytes */
     }
@@ -240,15 +240,4 @@
     }
 
-    if (total.last > lastart) {
-#ifdef SERVER
-	if (time(Null(time_t*)) - lastactfetch > MINFETCHTIME) {
-	    fclose(actfp);
-	    ngdata_init();	/* re-grab the active file */
-	}
-#endif
-	grow_ctl(total.last);	/* sets lastart */
-	ngmax[ng] = lastart;	/* ensure getngsize() knows the new maximum */
-    }
-
     if (!read_item(&author_cnts, (MEM_SIZE)total.author * sizeof (WORD))
      || !read_item(&strings, (MEM_SIZE)total.string1) 
@@ -309,4 +298,15 @@
 	    }
 	}
+    }
+
+    if (total.last > lastart) {
+#ifdef SERVER
+	if (time(Null(time_t*)) - lastactfetch > MINFETCHTIME) {
+	    fclose(actfp);
+	    ngdata_init();	/* re-grab the active file */
+	}
+#endif
+	grow_ctl(total.last);	/* sets lastart */
+	ngmax[ng] = lastart;	/* ensure getngsize() knows the new maximum */
     }
     count_roots(!saved_selections);
Index:rthreads.h
@@ -1,8 +1,3 @@
-/* $Id: rthreads.h,v 4.4.3.1 1991/11/22 04:12:18 davison Trn $
-**
-** $Log: rthreads.h,v $
-** Revision 4.4.3.1  1991/11/22  04:12:18  davison
-** Trn Release 2.0
-** 
+/* $Id: rthreads.h,v 2.3 1992/12/14 00:14:15 davison Trn $
 */
 
@@ -47,4 +42,5 @@
 int finish_tree ANSI((ART_LINE));
 void first_art ANSI((void));
+void next_art ANSI((void));
 void follow_thread ANSI((char_int));
 void backtrack_thread ANSI((char_int));
@@ -51,4 +47,5 @@
 void next_root ANSI((void));
 void prev_root ANSI((void));
+void next_article ANSI((void));
 char select_thread ANSI((char_int));
 int count_roots ANSI((bool_int));
@@ -55,4 +52,6 @@
 int count_one_root ANSI((int));
 PACKED_ARTICLE *upper_limit ANSI((PACKED_ARTICLE *,bool_int));
+PACKED_ARTICLE *find_prev_sib ANSI((void));
+PACKED_ARTICLE *find_next_sib ANSI((void));
 
 #define Nullart Null(PACKED_ARTICLE*)
Index:search.c
@@ -1,5 +1,8 @@
-/* $Id: search.c,v 4.4 1991/09/09 20:27:37 sob Exp sob $
+/* $Id: search.c,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
  *
  * $Log: search.c,v $
+ * Revision 4.4.3.1  1992/02/01  03:09:32  sob
+ * Release 4.4 Patchlevel 3
+ *
  * Revision 4.4  1991/09/09  20:27:37  sob
  * release 4.4
@@ -388,4 +391,5 @@
 	    p1++;
 	} while (*p1 && !err);
+	if (err) err = 0;
 	return Nullch;
     }
@@ -399,4 +403,5 @@
 	    p1++;
 	} while (*p1 && !err);
+	if (err) err = 0;
 	return Nullch;
     }
Index:server.c
@@ -37,4 +37,75 @@
 }
 
-#endif /* SERVER */
+# ifdef XTHREAD
+
+extern FILE *ser_rd_fp;
+
+static	long	rawbytes = -1;	/* bytes remaining to be transfered */
+
+/*
+ * rawcheck_server -- get a line of text from the server, interpreting
+ * it as a status message for a raw (binary) command.  Call this once
+ * before calling rawget_server() for the actual data transfer.
+ *
+ *	Parameters:	"string" has the buffer space for the
+ *			line received.
+ *			"size" is the size of the buffer.
+ *
+ *	Returns:	-1 on error, otherwise the length of the raw data.
+ *
+ *	Side effects:	Talks to server, changes contents of "string".
+ */
+long
+rawcheck_server(string, size)
+char	*string;
+int	size;
+{
+    /* try to get the status line and the status code */
+    if (get_server(string, size) || *string != CHAR_OK)
+	return rawbytes = -1;
+
+    /* try to get the number of bytes being transfered */
+    if (sscanf(string, "%*d%ld", &rawbytes) != 1)
+	return rawbytes = -1;
+    return rawbytes;
+}
 
+/*
+ * rawget_server -- read data from the server in raw format.  This call must
+ * follow an appropriate put_server command and a rawcheck_server call.
+ *
+ *	Parameters:	"buf" is the buffer for the data to receive.
+ *			"n" is the size of the buffer.
+ *
+ *	Returns:	0 on EOF, otherwise the length of the read.
+ *
+ *	Side effects:	Talks to server, changes contents of "buf".
+ */
+long
+rawget_server(buf, n)
+void	*buf;
+long	n;
+{
+    /* if no bytes to read, then just return EOF */
+    if (rawbytes < 0)
+	return 0;
+
+    /* try to read some data from the server */
+    if (rawbytes) {
+	n = fread(buf, 1, n > rawbytes ? rawbytes : n, ser_rd_fp);
+	rawbytes -= n;
+    } else
+	n = 0;
+
+    /* if no more left, then fetch the end-of-command signature */
+    if (!rawbytes) {
+	char buf[5];	/* "\r\n.\r\n" */
+
+	fread(buf, 1, 5, ser_rd_fp);
+	rawbytes = -1;
+    }
+    return n;
+}
+# endif
+
+#endif /* SERVER */
Index:server.h.SH
@@ -39,8 +39,12 @@
 EXT 	char ser_line[NNTP_STRLEN];
 
-# if defined(XTHREAD) && !defined(OK_BIN)
-     ??????  /* This version of NNTP doesn't have XTHREAD support */
+# ifdef HAVE_INN	/* if so, map NNTP defines into INN defines */
+#  define CHAR_OK	NNTP_CLASS_OK
+#  define CHAR_FATAL	NNTP_CLASS_FATAL
+#  define ERR_NOGROUP	NNTP_NOSUCHGROUP_VAL
+#  define OK_NOPOST	NNTP_NOPOSTOK_VAL
+#  define OK_CANPOST	NNTP_POSTOK_VAL
+#  define ERR_ACCESS	NNTP_ACCESS_VAL
 # endif
-
 #endif
 !GROK!THIS!
Index:sw.c
@@ -1,5 +1,8 @@
-/* $Id: sw.c,v 4.4 1991/09/09 20:27:37 sob Exp sob $
+/* $Id: sw.c,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
  *
  * $Log: sw.c,v $
+ * Revision 4.4.3.1  1992/02/01  03:09:32  sob
+ * Release 4.4 Patchlevel 3
+ *
  * Revision 4.4  1991/09/09  20:27:37  sob
  * release 4.4
@@ -45,7 +48,5 @@
     sw_file(tcbufptr,FALSE);
 #ifdef USETHREADS
-    if (use_threads)
-	safecpy(*tcbufptr,getval("TRNINIT",getenv("RNINIT")),1024);
-    else
+    if (!use_threads || !*safecpy(*tcbufptr,getenv("TRNINIT"),1024))
 #endif
 	safecpy(*tcbufptr,getenv("RNINIT"),1024);
@@ -199,6 +200,10 @@
 #endif
 	    break;
-	case 'c':
-	    checkflag = upordown;
+	case 'b':
+#ifdef USETHREADS
+	    breadth_first = upordown;
+#else
+	    notincl("-b");
+#endif
 	    break;
 	case 'C':
@@ -291,4 +296,7 @@
 	    initlines_specified = TRUE;
 	    break;
+	case 'j':
+	    dont_filter_control = TRUE;
+	    break;
 	case 'l':
 	    muck_up_clear = upordown;
@@ -452,4 +460,5 @@
     printf("%c/ ", mp[strEQ(getval("SAVEDIR",SAVEDIR),"%p/%c")]);
     printf("%ca ", mp[thread_always]);
+    printf("%cb ", mp[breadth_first]);
     printf("%cc ", mp[checkflag]);
     printf("-C%d ", docheckwhen);
@@ -474,4 +483,5 @@
 #endif
     printf("-i%d ", initlines);
+    printf("%cj ", mp[dont_filter_control]);
     printf("%cl ", mp[muck_up_clear]);
 #ifdef CLEAREOL
Index:sw.h
@@ -1,5 +1,8 @@
-/* $Id: sw.h,v 4.4 1991/09/09 20:27:37 sob Exp sob $
+/* $Id: sw.h,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
  *
  * $Log: sw.h,v $
+ * Revision 4.4.3.1  1992/02/01  03:09:32  sob
+ * Release 4.4 Patchlevel 3
+ *
  * Revision 4.4  1991/09/09  20:27:37  sob
  * release 4.4
Index:term.c
@@ -1,5 +1,8 @@
-/* $Id: term.c,v 4.4.2.1 1991/12/01 18:05:42 sob PATCH_2 sob $
+/* $Id: term.c,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
  *
  * $Log: term.c,v $
+ * Revision 4.4.3.1  1992/02/01  03:09:32  sob
+ * Release 4.4 Patchlevel 3
+ *
  * Revision 4.4.2.1  1991/12/01  18:05:42  sob
  * Patchlevel 2 changes
Index:term.h
@@ -1,5 +1,8 @@
-/* $Id: term.h,v 4.4 1991/09/09 20:27:37 sob Exp sob $
+/* $Id: term.h,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
  *
  * $Log: term.h,v $
+ * Revision 4.4.3.1  1992/02/01  03:09:32  sob
+ * Release 4.4 Patchlevel 3
+ *
  * Revision 4.4  1991/09/09  20:27:37  sob
  * release 4.4
Index:threads.c
@@ -1,8 +1,3 @@
-/* $Id: threads.c,v 4.4.3.1 1991/11/22 04:12:21 davison Trn $
-**
-** $Log:	threads.c,v $
-** Revision 4.4.3.1  1991/11/22  04:12:21  davison
-** Trn Release 2.0
-** 
+/* $Id: threads.c,v 2.3 1992/12/14 00:14:08 davison Trn $
 */
 
Index:threads.h
@@ -1,8 +1,3 @@
-/* $Id: threads.h,v 4.4.3.1 1991/11/22 04:12:21 davison Trn $
-**
-** $Log:	threads.h,v $
-** Revision 4.4.3.1  1991/11/22  04:12:21  davison
-** Trn Release 2.0
-** 
+/* $Id: threads.h,v 2.3 1992/12/14 00:14:09 davison Trn $
 */
 
Index:tm-process.c
@@ -1,8 +1,3 @@
-/* $Id: tm-process.c,v 4.4.3.1 1991/11/22 04:12:21 davison Trn $
-**
-** $Log: tm-process.c,v $
-** Revision 4.4.3.1  1991/11/22  04:12:21  davison
-** Trn Release 2.0
-** 
+/* $Id: tm-process.c,v 2.3 1992/12/14 00:14:16 davison Trn $
 */
 
Index:tm-read.c
@@ -1,8 +1,3 @@
-/* $Id: tm-read.c,v 4.4.3.1 1991/11/22 04:12:21 davison Trn $
-**
-** $Log: tm-read.c,v $
-** Revision 4.4.3.1  1991/11/22  04:12:21  davison
-** Trn Release 2.0
-** 
+/* $Id: tm-read.c,v 2.3 1992/12/14 00:14:17 davison Trn $
 */
 
Index:tm-write.c
@@ -1,8 +1,3 @@
-/* $Id: tm-write.c,v 4.4.3.1 1991/11/22 04:12:21 davison Trn $
-**
-** $Log: tm-write.c,v $
-** Revision 4.4.3.1  1991/11/22  04:12:21  davison
-** Trn Release 2.0
-** 
+/* $Id: tm-write.c,v 2.3 1992/12/14 00:14:18 davison Trn $
 */
 
Index:tmpthread.c
@@ -1,8 +1,3 @@
-/* $Id: tmpthread.c,v 4.4.3.1 1991/11/22 04:12:21 davison Trn $
-**
-** $Log: tmpthread.c,v $
-** Revision 4.4.3.1  1991/11/22  04:12:21  davison
-** Trn Release 2.0
-** 
+/* $Id: tmpthread.c,v 2.3 1992/12/14 00:14:19 davison Trn $
 */
 
@@ -22,11 +17,4 @@
 #include "mthreads.h"
 
-#ifdef TZSET
-#include <time.h>
-#else
-#include <sys/time.h>
-#include <sys/timeb.h>
-#endif
-
 struct stat filestat;
 
@@ -176,5 +164,5 @@
 	put_server("XTHREAD DBINIT");
 	rawcheck_server(buf, sizeof buf);
-	size = rawget_server((char*)&mt_bmap, sizeof (BMAP));
+	size = rawget_server((char*)&mt_bmap, (long)sizeof (BMAP));
 	if (size < sizeof (BMAP) - 1) {
 #else
@@ -204,5 +192,5 @@
 	}
 #ifdef XTHREAD
-	while (rawget_server(buf, sizeof buf)) {
+	while (rawget_server(buf, (long)sizeof buf)) {
 	    ;		/* trash any extraneous bytes */
 	}
Index:trn.1
@@ -1,3 +1,3 @@
-.\" $Id: trn.1,v 4.4.3.1 1991/11/22 04:13:39 davison Trn $
+.\" $Id: trn.1,v 2.3 1992/12/14 00:14:10 davison Trn $
 .\" 
 .\" This software is Copyright 1991 by Stan Barber. 
@@ -396,5 +396,5 @@
 Select the discussion thread by its letter or number;
 press again to deselect.
-By default the letters h, k, n, p, q, and y are omitted to allow them
+By default the letters c, h, k, n, p, q, and y are omitted to allow them
 to be typed as commands.
 See the variable SELECTCHARS to customize this.
@@ -439,4 +439,7 @@
 Mark unselected articles on the current page as read.
 Begin reading if articles are selected, otherwise go to the next page.
+.Ip c 8
+Catch up\*(--marks ALL articles as read without affecting their cross-posted
+counterparts.
 .Ip ^K 8
 Edit the local KILL file for this newsgroup.
@@ -463,5 +466,5 @@
 searching in the Article Selection section.
 .Sp
-One example:  to scan all the unread articles looking for \*(L"topic\*(L"
+One example:  to scan all the unread articles looking for \*(L"topic\*(R"
 anywhere in the article and then select its thread and save the article to
 the files topic.1, topic.2, etc. use \*(L"/topic/a:+:s topic.%#\*(R".
@@ -563,4 +566,6 @@
 Proceeds to the very first/last node if you're already at a root/leaf in
 a multi-root thread.
+.Ip "(,)" 8
+Go to the previous/next sibling in the thread, including \*(L"cousin\*(R" siblings.
 .Ip t 8
 Display the entire article tree and all its associated subjects.
@@ -596,5 +601,5 @@
 Applicable commands include \*(L'm\*(R' (mark as unread), \*(L'M\*(R'
 (delayed mark as unread), \*(L'j\*(R' (mark as read), \*(L"s dest\*(R"
-(save to a destination), \*(L"e dir"\*(R" (extract to directory),
+(save to a destination), \*(L"e dir\*(R" (extract to directory),
 \&\*(L"!command\*(R" (shell escape), \*(L"=\*(R" (print the subject),
 \&\*(L'T\*(R' (trash the thread into the local KILL file), \*(L'+\*(R'
@@ -650,5 +655,5 @@
 Applicable commands include \*(L'm\*(R' (mark as unread), \*(L'M\*(R'
 (delayed mark as unread), \*(L'j\*(R' (mark as read), \*(L"s dest\*(R"
-(save to a destination), \*(L"e dir"\*(R" (extract to directory),
+(save to a destination), \*(L"e dir\*(R" (extract to directory),
 \&\*(L"!command\*(R" (shell escape), \*(L"=\*(R" (print the subject),
 \&\*(L'T\*(R' (trash the associated thread and put it in the local KILL
@@ -1083,4 +1088,8 @@
 if no thread file for the group exists.
 .TP 5
+.B \-b
+will force trn to read each thread in a breadth-first order, rather than
+depth-first.
+.TP 5
 .B \-c
 checks for news without reading news.
@@ -1227,4 +1236,7 @@
 switch.)
 .TP 5
+.B \-j
+forces trn to leave control characters unmolested in messages.
+.TP 5
 .B \-l
 disables the clearing of the screen at the beginning of each
@@ -1848,5 +1860,5 @@
 Default:
 .Sp
-To: %T
+To: %t
 .br
 Subject: %(%i=^$?:Re: %S
@@ -1878,8 +1890,8 @@
 Default: %X/mbox.saver %A %P %c %a %B %C "%b" \e
 .br
-"From: %T %`date`"
+"From %T %`date`"
 .Sp
 Explanation: the first seven arguments are the same as for NORMSAVER.
-The eighth argument to the shell script is the new From: line
+The eighth argument to the shell script is the new From line
 for the article, including the posting date,
 derived either directly from the Posted: line, or not-so-directly from
Index:util.c
@@ -1,5 +1,11 @@
-/* $Id: util.c,v 4.4 1991/09/09 20:27:37 sob Exp sob $
+/* $Id: util.c,v 4.4.4.1 1992/02/23 21:25:39 sob PATCH_4 sob $
  *
  * $Log: util.c,v $
+ * Revision 4.4.4.1  1992/02/23  21:25:39  sob
+ * Patch level 4
+ *
+ * Revision 4.4.3.1  1992/02/01  03:09:32  sob
+ * Release 4.4 Patchlevel 3
+ *
  * Revision 4.4  1991/09/09  20:27:37  sob
  * release 4.4
@@ -27,11 +33,4 @@
 #include "util.h"
 
-#ifdef TZSET
-#include <time.h>
-#else
-#include <sys/time.h>
-#include <sys/timeb.h>
-#endif
-
 void
 util_init()
@@ -78,4 +77,5 @@
     signal(SIGQUIT, SIG_IGN);
 #endif 
+    termlib_reset();
     waiting = TRUE;
     while ((w = wait(&status)) != pid)
@@ -84,4 +84,5 @@
     if (w == -1)
 	status = -1;
+    termlib_init();
     waiting = FALSE;
     sigset(SIGINT, int_catcher);	/* always catch interrupts */
@@ -512,5 +513,5 @@
 #endif
 
-#ifndef STRFTIME
+#if defined(USETHREADS) && !defined(STRFTIME)
 /*
  * strftime: print formatted information about a given time.
@@ -706,5 +707,5 @@
 	    break;
 	case 't':	/* same as \t */
-	    putstr = "\n";
+	    putstr = "\t";
 	    break;
 	default:
@@ -727,3 +728,3 @@
     return num;
 }
-#endif /* no STRFTIME */
+#endif /* USETHREADS && no STRFTIME */
Index:uudecode.c
@@ -1,5 +1,8 @@
-/* $Id: uudecode.c,v 4.4.2.1 1991/12/01 18:05:42 sob PATCH_2 sob $
+/* $Id: uudecode.c,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
  *
  * $Log: uudecode.c,v $
+ * Revision 4.4.3.1  1992/02/01  03:09:32  sob
+ * Release 4.4 Patchlevel 3
+ *
  * Revision 4.4.2.1  1991/12/01  18:05:42  sob
  * Patchlevel 2 changes
---8<------8<------8<------8<---cut here--->8------>8------>8------>8---
Newsgroups: news.software.readers