[alt.sources] Patches to TRN 1.0.2 for remote threads via NNTP

iverson@xstor.com (Tim Iverson) (06/26/91)

This patch file requires patch-2.0.2.0 patchlevel 12u4.  You might have some
success with unipatch or earlier 12u* versions of patch, but you're on your
own there.  You will also need a virgin copy of trn 1.0.2.

What it does:	Adds support for the nntp XTHREAD command when compiled for
		use with an nntp server that supports XTHREAD.  This causes
		trn to get active2, db.init, and the thread files from the
		server, so you no longer need to run mthreads on the client
		machines.

To apply:	Build nntp with the XTHREAD command.  This patch uses some
		new functions in clientlib.c.  Then do
		patch -p < this_file

To compile:	sh ./Configure
		make depend
		make trn

The configure step is not optional.  It is needed to build the new server.h

You might also want to edit your client makefile/installation so that
mthreads and friends are neither compiled nor installed.

- Tim Iverson
  iverson@xstor.com -/- uunet!xstor!iverson

#
################ patch starts here
##
Prereq: v1.0.2
Index: patchlevel
@@ -1 +1 @@
-Trn v1.0.2
+Trn v1.0.2nntp
Index: Configure
@@ -2055,4 +2055,14 @@
=
=#include "$NNTPSRC/common/nntp.h"
+
+# if defined(OK_BIN) && defined(USETHREADS)
+#  define XTHREAD
+EXT	char	*nntp_thread_name;
+EXT	FILE	*nntp_active2(void);
+EXT	int	nntp_dbinit(void *buf, int size);
+EXT	void	nntp_thread(void);
+EXT	void	nntp_unlink(void);
+# endif
+
=#endif
=EOF_SERVE
Index: common.h
@@ -798,9 +798,17 @@
=/* how to cancel an article, continued */
=#ifndef CANCELHEADER
-#ifdef INTERNET
+# ifndef CMSG_HACK
+#  ifdef INTERNET
+#   define CANCELHEADER "From: %L@%H (%N)\nNewsgroups: %n\nSubject: cancel %i\nControl: cancel %i\nReferences: %R\nDistribution: %D\nOrganization: %o\n\nThis message was cancelled from within trn.\n"
+#  else
+#   define CANCELHEADER "From:%L@%H.UUCP (%N)\nNewsgroups: %n\nSubject: cancel %i\nControl: cancel %i\nReferences: %R\nDistribution: %D\nOrganization: %o\n"
+#  endif
+# else
+#  ifdef INTERNET
=#   define CANCELHEADER "From: %L@%H (%N)\nNewsgroups: %n\nSubject: cmsg cancel %i\nReferences: %R\nDistribution: %D\nOrganization: %o\n\nThis message was cancelled from within trn.\n"
-#else
+#  else
=#   define CANCELHEADER "From:%L@%H.UUCP (%N)\nNewsgroups: %n\nSubject: cmsg cancel %i\nReferences: %R\nDistribution: %D\nOrganization: %o\n"
-#endif
+#  endif
+# endif
=#endif
=
Index: final.c
@@ -56,4 +56,8 @@
=#include "final.h"
=
+#ifdef	SERVER
+# include "server.h"
+#endif
+
=void
=final_init()
@@ -112,4 +116,7 @@
= 	UNLINK(lockname);
=#ifdef SERVER
+# ifdef XTHREAD
+    nntp_unlink();
+# endif
=    if (*active_name)
=	UNLINK(active_name);
Index: ng.c
@@ -250,4 +250,9 @@
=    }
=
+#ifdef XTHREAD	/* use remote thread file? */
+# define thread_name(g)	nntp_thread_name
+    nntp_thread();
+#endif
+
=    /* FROM HERE ON, RETURN THRU CLEANUP OR WE ARE SCREWED */
=
@@ -651,4 +656,8 @@
=    mode = oldmode;
=    return exit_code;
+
+#ifdef	thread_name	/* undo the thread name patch (if active) */
+# undef thread_name
+#endif
=}					/* Whew! */
=
Index: ngdata.c
@@ -90,6 +90,11 @@
=#ifdef USETHREADS
=    if (use_threads) {
+# ifdef XTHREAD
+	cp = "server's active2";
+	actfp = nntp_active2();
+# else /* !XTHREADS */
=	cp = filexp(ACTIVE2);
=	actfp = fopen(cp,"r");
+# endif	/* XTHREAD */
=	if (actfp == Nullfp) {
=	    printf(cantopen,cp) FLUSH;
Index: nntp.c
@@ -0,0 +1,192 @@
+/* This file (and only this file - not the entire trn distribution) is
+ * hereby placed in the public domain.  Use it as you see fit, but if you
+ * manage to find some wonderful use for this code elsewhere, it would be
+ * nice to receive mention for it.
+ *
+ * - Tim Iverson
+ *   iverson@xstor.com -/- uunet!xstor!iverson
+ *   3/29/91
+ */
+
+#include "EXTERN.h"
+#include "common.h"
+#include "server.h"
+
+#ifdef XTHREAD
+
+# ifdef __GNUC__
+#  define alloca __builtin_alloca
+# endif
+
+static	char		/* tmp file names */
+	tmp_active2[]	= "/tmp/12345678901234",
+	tmp_thread[]	= "/tmp/12345678901234";
+
+static	int		/* !0 indicates tmp file has been created */
+	got_active2	= 0,
+	got_thread	= 0;
+
+char	*nntp_thread_name = NULL;
+
+
+/* This function returns a pointer to an open file containing a copy of the
+ * current active2 file on the server.
+ *
+ * entry:	it is assumed the server is already open and accessible via
+ *		the put_server() and get_server() functions.
+ *
+ * exit:	on success, tmp file to hold server's active2 has been created
+ *
+ * return:	file pointer opened for reading on success, NULL on failure.
+ */
+FILE *
+nntp_active2()
+{
+	char	ser_line[512];
+	FILE	*fp;
+
+	/* check to see if the server will even give us the active2 file */
+	put_server("LIST ACTIVE2");
+	if (get_server(ser_line, sizeof(ser_line)) || (*ser_line != CHAR_OK))
+		return NULL;		/* server won't/can't give it to us */
+
+	/* first try to create the tmp file */
+	if (!got_active2)
+	{
+		sprintf(tmp_active2, "/tmp/rrnact2.%u", getpid());
+		if (!(fp = fopen(tmp_active2, "w")))
+			return NULL;
+		got_active2 = 1;
+	}
+
+	/* data is now waiting to be picked up - try to create the tmp file */
+	while (!get_server(ser_line, sizeof(ser_line)))
+	{
+		if (ser_line[0] == '.' && !ser_line[1])
+			break;
+		fprintf(fp, "%s\n", ser_line);
+	}
+
+	/* reopen the file for reading */
+	return fp = freopen(tmp_active2, "r", fp);
+}
+
+
+
+/* Load buf with the ouput of XTHREAD DBINIT.  Don't exceed size bytes and
+ * return the actual number of bytes sent.
+ */
+int
+nntp_dbinit(buf, size)
+void	*buf;
+int	size;
+{
+	int	rsize;
+	char	*rbuf;
+
+	/* first try to do the command */
+	if (!(rsize = xthread("DBINIT")))
+		return rsize;
+
+	/* get space for the all of the bytes */
+	if (!(rbuf = alloca(rsize)))
+		return 0;
+
+	xthread_read(rbuf, rsize);
+	memcpy(buf, rbuf, rsize > size ? size : rsize);
+	return rsize;
+}
+
+
+
+/* Get the thread for the current GROUP and put it in a tmp file.  The
+ * tmp file name is then placed in nntp_thread_name.
+ *
+ * entry:	the nntp GROUP command has been used to select the
+ *		desired newsgroup.  ser_rd_fp and ser_wr_fp (the server
+ *		read and write file pointers) are open; i.e. server_init()
+ *		has been performed successfully.
+ *
+ * exit:	a tmp file to hold the thread file from the server is
+ *		created and nntp_thread_name is set to point at the
+ *		name of that file.  On failure, nntp_thread_name is
+ *		set to point at the name of an empty file (/dev/null).
+ */
+void
+nntp_thread()
+{
+	int	size;
+	char	*buf;
+	FILE	*fp;
+
+	/* start out as a pessimist */
+	nntp_thread_name = "/dev/null";
+
+	/* first try to do the command */
+	if (!(size = xthread(NULL)))
+		return;
+
+	/* get space for the all of the bytes */
+	if (!(buf = alloca(size)))
+		return;
+
+	/* read it in in one big gulp */
+	xthread_read(buf, size);
+
+	/* make sure we've got a place for the thread file */
+	if (!got_thread)
+	{
+		sprintf(tmp_thread, "/tmp/rrnthd.%u", getpid());
+		got_thread = 1;
+	}
+
+	/* try to create/open the tmp file */
+	if (!(fp = fopen(tmp_thread, "w")))
+		return;
+
+	/* write it out unbuffered */
+	write(fileno(fp), buf, size);
+	fclose(fp);
+	nntp_thread_name = tmp_thread;
+}
+
+
+
+/* Remove all temporary files used so far by the nntp support module.
+ * This routine could be much more general (and should if tmp files start
+ * proliferating).
+ */
+void
+nntp_unlink()
+{
+	if (got_active2)
+		UNLINK(tmp_active2);
+	if (got_thread)
+		UNLINK(tmp_thread);
+	got_active2 = got_thread = 0;
+}
+
+
+# if defined(M_XENIX) && !defined(M_UNIX)	/* sco xenix lacks memmove */
+
+/* ansi memmove function for non-ansi compilers
+ */
+void *
+memmove(d, s, n)
+char	*d,
+	*s;
+size_t	n;
+{
+	void	*r = d;
+
+	if (d < s) while (n--)
+		*d++ = *s++;
+	else for (d += n, s += n; n; --n)
+		*--d = *--s;
+
+	return r;
+}
+
+# endif /* M_XENIX */
+
+#endif /* not XTHREAD */
Index: rn.c
@@ -11,5 +11,5 @@
=
=static char rnid[] = "@(#)$Header: rn.c,v 4.3.3.3 91/01/16 03:28:42 davison Trn $";
-static char patchlevel[] = "Trn v1.0.2 based on Rn patchlevel 54";
+static char patchlevel[] = "Trn v1.0.2 (with nntp threads) based on Rn patchlevel 54";
=
=/* $Log:	rn.c,v $
Index: rthreads.c
@@ -21,4 +21,8 @@
=#include "rthreads.h"
=
+#ifdef	SERVER
+# include "server.h"
+#endif
+
=static FILE *fp_in;
=
@@ -40,7 +44,11 @@
=
=    word_same = long_same = TRUE;
+#ifdef	XTHREAD
+    if (nntp_dbinit(&mt_bmap, sizeof mt_bmap) >= sizeof mt_bmap - 1) {
+#else	/* !XTHREAD */
=    filename = filexp( "%X/db.init" );
=    if( (fp_in = fopen( filename, FOPEN_RB )) != Nullfp ) {
=	if( fread( &mt_bmap, 1, sizeof (BMAP), fp_in ) >= sizeof (BMAP)-1 ) {
+#endif	/* XTHREAD */
=	    if( mt_bmap.version != DB_VERSION ) {
=		printf( "\nThread database is the wrong version -- ignoring it.\n" ) FLUSH;
@@ -58,4 +66,5 @@
=		}
=	    }
+#ifndef	XTHREAD
=	} else {
=	    goto no_db_init;
@@ -62,4 +71,5 @@
=	}
=	fclose( fp_in );
+#endif	/* XTHREAD */
=    } else {
=      no_db_init:
##
################ patch ends here
#