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. Basically, it extends the nntp command set to allow trn to retrieve thread information via nntp - the need for a local threads database is eliminated. What it does: modifies the LIST command to also list trn's active2 file. adds an XTHREAD command so trn can access threads remotely. To apply: cd nntp-1.5.11 patch -p < this_file To compile: None of the installation files or Makefiles are modified, so you will have to follow the directions included with nntp. For SCO Unix, you should apply the sco unix patch. - Tim Iverson iverson@xstor.com -/- uunet!xstor!iverson # ################ patch starts here ## Prereq: "1.5.11 Index: common/version.c @@ -3,3 +3,3 @@ = */ = -char nntp_version[] = "1.5.11 (10 February 1991)"; +char nntp_version[] = "1.5.11a (1 April 1991)"; Index: common/clientlib.c @@ -634,2 +634,72 @@ =} = + + +static int bytes = 0; /* bytes remaining to be transfered */ + +/* This function issues an XTHREAD command and prepares xthread_read() for + * the data transfer by reading the status line returned by the server. + * + * entry: server must be open and ready to accept commands. + * + * exit: server will be transfering XTHREAD data. + * + * return: bytes to be transfered on success, 0 for error. + */ +int +xthread(cmd) +char *cmd; +{ + char buf[512]; + + /* send the given xthread command */ + sprintf(buf, cmd && *cmd ? "XTHREAD %s\r\n" : "XTHREAD\r\n", cmd); + put_server(buf); + + /* try to get the status line and the status code */ + if (get_server(buf, sizeof buf) || *buf != CHAR_OK) + return bytes = 0; + + /* try to get the number of bytes being transfered */ + if (sscanf(buf, "%*d%d", &bytes) != 1) + return bytes = 0; + return bytes; +} + + +/* This function is used to read the data sent as a result of the + * XTHREAD command. + * + * entry: There must have been a successful call to xthread() or + * xthread_read() preceding the current call. + * + * No other communication to or from the server after XTHREAD is + * issued and before this function returns EOF or error is + * allowed - otherwise we'll block for data that'll never come. + * + * exit: The buffer is filled with data from the XTHREAD command. + * + * return: bytes read into the buffer, 0 for eof or error. + */ +int +xthread_read(buf, n) +void *buf; +int n; +{ + /* if no bytes to read, then just return EOF */ + if (!bytes) + return bytes; + + /* try to read some data from the server */ + bytes -= (n = fread(buf, 1, n > bytes ? bytes : n, ser_rd_fp)); + + /* if no more left, then fetch the end-of-command signature */ + if (!bytes) + { + char buf[5]; /* "\r\n.\r\n" */ + + fread(buf, sizeof buf, 1, ser_rd_fp); + } + + return n; +} Index: common/clientlib.h @@ -10,2 +10,4 @@ =extern int get_server(); =extern void close_server(); +extern int xthread(); +extern int xthread_read(); Index: common/conf.h.dist @@ -95,4 +95,13 @@ = /* loaded already, defining this may be a bad idea */ = +#define XTHREAD /* Optional XTHREAD command. This allows trn to + * keep all data on the server. + */ + +#ifdef XTHREAD /* locations for trn data files (on server) */ +# define ACTIVE2_FILE "/usr/local/lib/trn/active2" +# define DBINIT_FILE "/usr/local/lib/trn/db.init" +#endif + =/* Things that vary in network implementations */ =#define SUBNET /* If you have 4.3 subnetting */ Index: common/nntp.h @@ -49,4 +49,5 @@ =#define OK_AUTHSYS 280 /* Authorization system ok */ =#define OK_AUTH 281 /* Authorization (user/pass) ok */ +#define OK_BIN 282 /* binary data follows */ = =#define CONT_XFER 335 /* Continue to send article */ Index: server/Makefile @@ -7,5 +7,5 @@ = newgroups.o newnews.o nextlast.o ngmatch.o post.o parsit.o scandir.o \ = slave.o spawn.o strcasecmp.o subnet.o time.o xhdr.o fakesyslog.o \ - batch.o auth.o timer.o ../common/version.o + batch.o auth.o timer.o xthread.o ../common/version.o = =SRVRSRC = main.c serve.c access.c access_inet.c access_dnet.c active.c \ @@ -13,5 +13,5 @@ = newgroups.c newnews.c nextlast.c ngmatch.c post.c parsit.c scandir.c \ = slave.c spawn.c strcasecmp.c subnet.c time.c xhdr.c fakesyslog.c \ - batch.c auth.c timer.c ../common/version.c + batch.c auth.c timer.c xthread.c ../common/version.c = =SRVRINC = common.h ../common/conf.h ../common/nntp.h timer.h @@ -19,4 +19,6 @@ =SRCS = ${SRVRSRC} = +THREADS = ../../trn/threads.o + =# -ldbm here if you've #define'ed DBM in ../common/conf.h =LIBS = -ldbm @@ -30,8 +32,12 @@ =all: nntpd = -nntpd: ${SRVROBJ} ${SRVRINC} - ${CC} ${CFLAGS} -o nntpd ${SRVROBJ} ${LIBS} +nntpd: ${SRVROBJ} ${SRVRINC} ${THREADS} + ${CC} ${CFLAGS} -o nntpd ${SRVROBJ} ${THREADS} ${LIBS} = =${SRVROBJ}: ${SRVRINC} + +$(THREADS) : + @echo You must first build threads.o as used in trn. + @false = =install: nntpd Index: server/common.h @@ -165,4 +165,10 @@ =extern char rnews[]; = +#ifdef XTHREAD +extern char active2file[]; +extern char dbinitfile[]; +extern char *threadfile; +#endif + =extern char **group_array; =extern char *actbuf; Index: server/globals.c @@ -27,4 +27,10 @@ =char rnews[] = RNEWS; = +#ifdef XTHREAD +char active2file[] = ACTIVE2_FILE; +char dbinitfile[] = DBINIT_FILE; +char *threadfile = NULL; +#endif + =/* = * Other random externals. Index: server/group.c @@ -101,4 +101,12 @@ = *cp = '.'; = +#ifdef XTHREAD + { + extern char *thread_name(const char *newsgroup); + + threadfile = thread_name(argv[1]); + } +#endif + = printf("%d %d %d %d %s\r\n", = OK_GROUP, Index: server/help.c @@ -22,6 +22,13 @@ = 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"); +# ifdef XHDR = printf("XHDR Retrieve a single header line from a range of articles.\r\n"); +# endif XHDR +# ifdef XTHREAD + printf("XTHREAD Retrieve trn thread file for the current group.\r\n"); +# endif +#endif = printf("\r\n"); = printf("Bugs to Stan Barber (Internet: nntp@tmc.edu; UUCP: ...!bcm!nntp)\r\n"); Index: server/list.c @@ -46,6 +46,27 @@ = items = "newsgroup descriptions"; = format = "Descriptions in form \"group description\"."; +#ifdef XTHREAD + } else if (argc == 2 && !strcasecmp(argv[1],"active2")){ + num_groups = read_groups(); + if (num_groups == 0){ /* can't get a group list */ + printf("%d Group update failed. Try later.\r\n", + ERR_FAULT); + (void) fflush(stdout); +# ifdef LOG + syslog(LOG_INFO, "%s group update failed in LIST", hostname); +# endif + exit(1); + } + filename = active2file; + items = "threaded newsgroups"; + format = "Threaded groups in form \"group high low y/n/m\"."; +#endif /* XTHREAD */ = } else { - printf("%d Usage: LIST [ACTIVE|NEWSGROUPS|DISTRIBUTIONS]\r\n", + printf( +#ifdef XTHREAD + "%d Usage: LIST [ACTIVE|ACTIVE2|DISTRIBUTIONS|NEWSGROUPS]\r\n", +#else + "%d Usage: LIST [ACTIVE|NEWSGROUPS|DISTRIBUTIONS]\r\n", +#endif /* XTHREAD */ = ERR_CMDSYN); = (void) fflush(stdout); 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(); +extern int slave(), stat(), xhdr(), xthread(); = =extern int errno; @@ -62,4 +62,7 @@ = "xhdr", 0, xhdr, =#endif XHDR +#ifdef XTHREAD + "xthread", 0, xthread, +#endif =}; =#define NUMCMDS (sizeof(cmdtbl) / sizeof(struct cmdent)) Index: server/xthread.c @@ -0,0 +1,115 @@ +/* This file (and only this file - not the entire nntp 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/28/91 + */ + +#include "common.h" + +#ifdef XTHREAD + +# ifdef __GNUC__ +# define alloca __builtin_alloca +# else +extern void *alloca(unsigned int bytes); +# endif + + +/* Usage: XTHREAD [DBINIT|THREAD] + * + * DBINIT dump the contents of the db.init file to stdout + * THREAD dump the contents of the thread file for the current + * newsgroup to stdout (default if no argument). + * + * N.B. These two files are not ascii and no attempt is made at converting + * native byte size to any type of standard whatsoever. This'll have + * to be fixed if this command is to be integrated into the protocol. + * + * This command is not documented in rfc977. + */ + +void +xthread(argc, argv) +int argc; +char *argv[]; +{ + register FILE *fp; + struct stat s; + char *buf, *file, *what; + + /* can't transfer threads, only read 'em */ + if (!canread) + { + printf("%d You only have permission to transfer, sorry.\r\n", + ERR_ACCESS); + (void) fflush(stdout); + return; + } + + /* "parse" the argument */ + if (argc == 2 && !strcasecmp(argv[1], "dbinit")) + { + file = dbinitfile; + what = "db.init"; + } + else if (argc == 1 || argc == 2 && !strcasecmp(argv[1], "thread")) + { + if (!threadfile) + { + printf("%d You are not currently in a newsgroup.\r\n", + ERR_NCING); + (void) fflush(stdout); + return; + } + file = threadfile; + what = "thread"; + } + else + { + printf("%d Usage: XTHREAD [DBINIT|THREAD]\r\n", ERR_CMDSYN); + (void) fflush(stdout); + return; + } + + /* try to open the file to be transfered */ + if (!(fp = fopen(file, "r"))) + { + printf("%d %s file is not available.\r\n", ERR_FAULT, what); + (void) fflush(stdout); +#ifdef SYSLOG + syslog(LOG_ERR, "xthread: fopen %s: %m", file); +#endif + return; + } + + /* tell 'em how much binary data is coming down the pike */ + fstat(fileno(fp), &s); + printf("%d %u bytes of %s file follows verbatim " + "(binary!)\r\n", OK_BIN, s.st_size, what); + + /* copy the file verbatim to stdout */ + if (buf = alloca(s.st_size)) + { + /* ah-so! got lotsa memoree */ + read(fileno(fp), buf, s.st_size); + fwrite(buf, s.st_size, 1, stdout); + } + else + { + int bytes; + char buf[BUFSIZ]; + + while (bytes = fread(buf, 1, sizeof buf, fp)) + fwrite(buf, bytes, 1, stdout); + } + + fputs("\r\n.\r\n", stdout); + fflush(stdout); + fclose(fp); +} + +#endif /* not XTHREAD */ ## ################ patch ends here #