v23i064: TRN, version of RN that follows conversation threads, Part05/14

Rich Salz rsalz at bbn.com
Sat Dec 1 08:40:19 AEST 1990


Submitted-by: Wayne Davison <davison at dri.com>
Posting-number: Volume 23, Issue 64
Archive-name: trn/part05

---- Cut Here and unpack ----
#!/bin/sh
# this is part 5 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file art.c continued
#
CurArch=5
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file art.c"
sed 's/^X//' << 'SHAR_EOF' >> art.c
X	      FLUSH;
X#endif
X	return TRUE;
X    }
X    if (artpos == innersearch) {	/* just got onto page? */
X	isrchline = artline;		/* remember first line after */
X	highlight = artline - 1;
X#ifdef DEBUGGING
X	if (debug & DEB_INNERSRCH)
X	    printf("There it is %ld = %ld, %d @ %d\n",(long)artpos,
X		(long)innersearch,hide_everything,highlight) FLUSH;
X#endif
X	if (hide_everything) {		/* forced refresh? */
X	    topline = highlight - gline;
X	    if (topline < -1)
X		topline = -1;
X	    return FALSE;		/* let refresh do it all */
X	}
X    }
X#ifdef DEBUGGING
X    if (debug & DEB_INNERSRCH)
X	printf("Not far enough? %d <? %d + %d\n",artline,isrchline,gline)
X	  FLUSH;
X#endif
X    if (artline < isrchline + gline) {
X	return TRUE;
X    }
X    return FALSE;
X}
X#endif
SHAR_EOF
echo "File art.c is complete"
chmod 0660 art.c || echo "restore of art.c fails"
echo "x - extracting art.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > art.h &&
X/* $Header: art.h,v 4.3 85/05/01 11:35:29 lwall Exp $
X *
X * $Log:	art.h,v $
X * Revision 4.3  85/05/01  11:35:29  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
X/* do_article() return values */
X
X#define DA_NORM 0
X#define DA_RAISE 1
X#define DA_CLEAN 2
X#define DA_TOEND 3
X
Xvoid	art_init();
Xint	do_article();
Xint	page_switch();
Xbool	innermore();
SHAR_EOF
chmod 0660 art.h || echo "restore of art.h fails"
echo "x - extracting artio.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > artio.c &&
X/* $Header: artio.c,v 4.3.3.1 90/07/21 20:11:03 davison Trn $
X *
X * $Log:	artio.c,v $
X * Revision 4.3.3.1  90/07/21  20:11:03  davison
X * Initial Trn Release
X * 
X * Revision 4.3.2.5  90/03/22  23:04:04  sob
X * Fixes provided by Wayne Davison <drivax!davison>
X * 
X * Revision 4.3.2.4  89/11/27  01:29:57  sob
X * Altered NNTP code per ideas suggested by Bela Lubkin
X * <filbo at gorn.santa-cruz.ca.us>
X * 
X * Revision 4.3.2.3  89/11/26  22:55:31  sob
X * Add nntpopen() and nntpclose() routines to cut down on size of rrn
X * 
X * Revision 4.3.2.2  89/11/08  01:17:12  sob
X * Added changes to insure that this will compile for RN or RRN with no
X * changes to the source code.
X * 
X * Revision 4.3.2.1  89/11/06  00:07:25  sob
X * Added RRN support from NNTP 1.5
X * 
X * Revision 4.3  85/05/01  11:35:39  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#ifdef SERVER
X#include "server.h"
X#endif
X#include "INTERN.h"
X#include "artio.h"
X
Xvoid
Xartio_init()
X{
X    ;
X}
X
X/* open an article, unless it's already open */
X
XFILE *
Xartopen(artnum)
XART_NUM artnum;
X{
X#ifdef SERVER
X    nntpopen(artnum,GET_ARTICLE);
X#else
X    char artname[32];			/* filename of current article */
X
X    if (artnum < 1)
X	return Nullfp;
X    if (openart == artnum) {		/* this article is already open? */
X	fseek(artfp,0L,0);		/* just get to the beginning */
X	return artfp;			/* and say we succeeded */
X    }
X    if (artfp != Nullfp) {		/* it was somebody else? */
X	fclose(artfp);			/* put them out of their misery */
X	openart = 0;			/* and remember them no more */
X    }
X    sprintf(artname,"%ld",(long)artnum);
X					/* produce the name of the article */
X    if (artfp = fopen(artname,"r"))	/* if we can open it */
X	openart = artnum;		/* remember what we did here */
X#endif /* SERVER */
X#ifdef LINKART
X    {
X	char tmpbuf[256];
X	char *s;
X
X	if (fstat(artfp->_file,&filestat))
X	    return artfp;
X	if (filestat.st_size < (sizeof tmpbuf)) {
X	    fgets(tmpbuf,(sizeof tmpbuf),artfp);
X	    if (*tmpbuf == '/') {	/* is a "link" to another article */
X		fclose(artfp);
X		if (s=index(tmpbuf,'\n'))
X		    *s = '\0';
X		if (!(artfp = fopen(tmpbuf,"r")))
X		    openart = 0;
X		else {
X		    if (*linkartname)
X			free(linkartname);
X		    linkartname = savestr(tmpbuf);
X		}
X	    }
X	    else
X		fseek(artfp,0L,0);		/* get back to the beginning */
X	}
X    }
X#endif
X    return artfp;			/* and return either fp or NULL */
X}
X
X#ifdef SERVER
Xstatic long our_pid;
X
XFILE *
Xnntpopen(artnum,function)
XART_NUM artnum;
XART_PART function;
X{
X    char ser_line[256];
X    char artname[32];			/* filename of current article */
X    if (our_pid == 0)
X	our_pid = getpid();
X    if (artnum < 1)
X	return Nullfp;
X    if ((openart == artnum) && (openpart >= function))
X    {					/* this article is already open? */
X	fseek(artfp,0L,0);		/* just get to the beginning */
X	return artfp;			/* and say we succeeded */
X    }
X    if (artfp != Nullfp) {		/* it was somebody else? */
X	fclose(artfp);			/* put them out of their misery */
X	nntpclose();
X	openart = 0;			/* and remember them no more */
X    }
X    sprintf(artname,"/tmp/rrn%ld.%ld", (long) artnum, our_pid);
X    artfp = fopen(artname, "w+");	/* create the temporary article */
X    if (artfp == Nullfp) {
X	UNLINK(artname);
X	return Nullfp;
X    }
X    switch (function){
X	    case GET_STATUS:
X		function = GET_HEADER;	/* fall through */
X	    case GET_HEADER:
X		sprintf(ser_line, "HEAD %ld", (long)artnum);
X		break;
X	    case GET_ARTICLE:
X		sprintf(ser_line, "ARTICLE %ld", (long)artnum);
X		break;
X    }	    
X    put_server(ser_line);		/* ask the server for the article */
X    if (get_server(ser_line, sizeof(ser_line)) < 0) {
X	fprintf(stderr, "rrn: Unexpected close of server socket.\n");
X	finalize(1);
X    }
X    if (*ser_line != CHAR_OK) {		/* and get it's reaction */
X	fclose(artfp);
X	artfp = Nullfp;
X	UNLINK(artname);
X 	errno = ENOENT;		/* Simulate file-not-found */
X        return Nullfp;
X    }
X
X    for (;;) {
X        if (get_server(ser_line, sizeof(ser_line)) < 0) {
X	    fprintf(stderr, "rrn: Unexpected close of server socket.\n");
X	    finalize(1);
X	}
X	if (ser_line[0] == '.' && ser_line[1] == '\0')
X		break;
X	fputs((ser_line[0] == '.' ? ser_line + 1 : ser_line), artfp);
X	putc('\n', artfp);
X    }
X    openpart = function;
X    if (function == GET_HEADER)
X	 putc('\n', artfp); /* req'd blank line after header */
X    fseek(artfp, 0L, 0);		/* Then get back to the start */
X    openart = artnum;
X    return artfp;			/* and return either fp or NULL */
X}
X
Xvoid
Xnntpclose()
X{
X    char artname[32];			/* filename of current article */
X    if (our_pid == 0)
X	our_pid = getpid();
X    sprintf(artname, "/tmp/rrn%ld.%ld", (long) openart, our_pid);
X    UNLINK(artname);
X}
X#endif
SHAR_EOF
chmod 0660 artio.c || echo "restore of artio.c fails"
echo "x - extracting artio.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > artio.h &&
X/* $Header: artio.h,v 4.3.3.1 90/07/21 20:12:10 davison Trn $
X *
X * $Log:	artio.h,v $
X * Revision 4.3.3.1  90/07/21  20:12:10  davison
X * Initial Trn Release
X * 
X * Revision 4.3.2.2  89/11/27  01:27:53  sob
X * Altered NNTP code per ideas suggested by Bela Lubkin
X * <filbo at gorn.santa-cruz.ca.us>
X * 
X * Revision 4.3.2.1  89/11/26  22:41:24  sob
X * Added RRN support
X * 
X * Revision 4.3  85/05/01  11:35:43  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
XEXT ART_POS artpos INIT(0);	/* byte position in article file */
X
XEXT ART_LINE artline INIT(0);		/* current line number in article file */
XEXT FILE *artfp INIT(Nullfp);		/* current article file pointer */
XEXT ART_NUM openart INIT(0);		/* what is the currently open article number? */
X#ifdef LINKART
X    EXT char *linkartname INIT(nullstr);/* real name of article for Eunice */
X#endif
X#ifdef SERVER
XEXT ART_PART openpart INIT(0);	/* how much of that article do we have? */
XFILE	*nntpopen();		/* get an article unless already retrieved */
X
Xvoid	nntpclose();
X/* MUST be in increasing order of completeness! */
X#define GET_STATUS	1		/* test for existence only */
X#define GET_HEADER	2		/* if only header items are desired */
X#define GET_ARTICLE	3		/* retreive full article  */
X#endif
X
Xvoid	artio_init();
XFILE	*artopen();		/* open an article unless already opened */
SHAR_EOF
chmod 0660 artio.h || echo "restore of artio.h fails"
echo "x - extracting artsrch.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > artsrch.c &&
X/* $Header: artsrch.c,v 4.3.3.1 90/07/21 20:13:13 davison Trn $
X *
X * $Log:	artsrch.c,v $
X * Revision 4.3.3.1  90/07/21  20:13:13  davison
X * Initial Trn Release
X * 
X * Revision 4.3.2.4  89/11/27  01:30:00  sob
X * Altered NNTP code per ideas suggested by Bela Lubkin
X * <filbo at gorn.santa-cruz.ca.us>
X * 
X * Revision 4.3.2.3  89/11/26  22:54:37  sob
X * Added new patches to make rrn faster.
X * 
X * Revision 4.3.2.2  89/11/26  22:20:57  sob
X * Added better NNTP support.
X * 
X * Revision 4.3.2.1  89/11/26  22:13:10  sob
X * Added support for NNTP
X * 
X * Revision 4.3  85/05/01  11:35:47  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "search.h"
X#include "term.h"
X#include "util.h"
X#include "intrp.h"
X#include "bits.h"
X#include "kfile.h"
X#include "head.h"
X#include "final.h"
X#include "cheat.h"
X#ifdef SERVER
X#include "server.h"
X#endif
X#include "ng.h"
X#include "artio.h"
X#ifdef USETHREADS
X#include "rthreads.h"
X#include "ngdata.h"
X#endif
X#include "INTERN.h"
X#include "artsrch.h"
X
Xvoid
Xartsrch_init()
X{
X#ifdef ARTSEARCH
X#ifdef ZEROGLOB
X    init_compex(&sub_compex);
X    init_compex(&art_compex);
X#endif
X#endif
X}
X
X/* search for an article containing some pattern */
X
X#ifdef ARTSEARCH
Xint
Xart_search(patbuf,patbufsiz,get_cmd)
Xchar *patbuf;				/* if patbuf != buf, get_cmd must */
Xint patbufsiz;
Xint get_cmd;				/*   be set to FALSE!!! */
X{
X    char *pattern;			/* unparsed pattern */
X    register char cmdchr = *patbuf;	/* what kind of search? */
X    register char *s;
X    bool backward = cmdchr == '?' || cmdchr == Ctl('p');
X					/* direction of search */
X    COMPEX *compex;			/* which compiled expression */
X    char *cmdlst = Nullch;		/* list of commands to do */
X    int normal_return = SRCH_NOTFOUND;	/* assume no commands */
X    bool saltaway = FALSE;		/* store in KILL file? */
X    char howmuch;			/* search just the subjects */
X    bool doread;			/* search read articles? */
X    bool foldcase = TRUE;		/* fold upper and lower case? */
X
X    int_count = 0;
X    if (cmdchr == '/' || cmdchr == '?') {	/* normal search? */
X	if (get_cmd && buf == patbuf)
X	    if (!finish_command(FALSE))	/* get rest of command */
X		return SRCH_ABORT;
X	compex = &art_compex;
X	if (patbuf[1]) {
X	    howmuch = 0;
X	    doread = FALSE;
X	}
X	else {
X	    howmuch = art_howmuch;
X	    doread = art_doread;
X	}
X	s = cpytill(buf,patbuf+1,cmdchr);/* ok to cpy buf+1 to buf */
X	pattern = buf;
X	if (*pattern) {
X	    if (*lastpat)
X		free(lastpat);
X	    lastpat = savestr(pattern);
X	}
X	if (*s) {			/* modifiers or commands? */
X	    for (s++; *s && index("Kharc",*s); s++) {
X		if (*s == 'h')		/* scan header */
X		    howmuch = 1;
X		else if (*s == 'a')	/* scan article */
X		    howmuch = 2;
X		else if (*s == 'r')	/* scan read articles */
X		    doread = TRUE;
X		else if (*s == 'K')	/* put into KILL file */
X		    saltaway = TRUE;
X		else if (*s == 'c')	/* make search case sensitive */
X		    foldcase = FALSE;
X	    }
X	}
X	while (isspace(*s) || *s == ':')
X	    s++;
X	if (*s) {
X	    if (*s == 'm' || *s == 'M')
X		doread = TRUE;
X	    if (*s == 'k')		/* grandfather clause */
X		*s = 'j';
X	    cmdlst = savestr(s);
X	    normal_return = SRCH_DONE;
X	}
X	art_howmuch = howmuch;
X	art_doread = doread;
X	if (srchahead)
X	    srchahead = -1;
X    }
X    else {
X	register char *h;
X
X	howmuch = 0;			/* just search subjects */
X	doread = (cmdchr == Ctl('p'));
X	if (cmdchr == Ctl('n'))
X	    normal_return = SRCH_SUBJDONE;
X	compex = &sub_compex;
X	pattern = patbuf+1;
X	strcpy(pattern,": *");
X	h = pattern + strlen(pattern);
X	interp(h,patbufsiz - (h-patbuf),"%s");	/* fetch current subject */
X	if (cmdchr == 'K') {
X	    saltaway = TRUE;
X	    cmdchr = 'k';
X	}
X	if (cmdchr == 'k') {
X	    normal_return = SRCH_DONE;
X	    cmdlst = savestr("j");
X	    mark_as_read();		/* this article has this subject */
X	    if (!*h) {
X#ifdef VERBOSE
X		IF(verbose)
X		    fputs("\nCannot delete null subject.\n",stdout) FLUSH;
X		ELSE
X#endif
X#ifdef TERSE
X		    fputs("\nNull subject.\n",stdout) FLUSH;
X#endif
X		return SRCH_ABORT;
X	    }
X#ifdef VERBOSE
X	    else if (verbose)
X		printf("\nMarking subject \"%s\" as read.\n",h) FLUSH;
X#endif
X	}
X	else if (!srchahead)
X	    srchahead = -1;
X	h[24] = '\0';		/* compensate for notesfiles */
X	while (*h) {
X	    if (index("/\\[.^*$'\"",*h) != Nullch)
X		*h++ = '.';
X	    else
X		h++;
X	}
X#ifdef DEBUGGING
X	if (debug) {
X	    printf("\npattern = %s\n",pattern) FLUSH;
X	}
X#endif
X    }
X    if ((s = compile(compex,pattern,TRUE,foldcase)) != Nullch) {
X					/* compile regular expression */
X	printf("\n%s\n",s) FLUSH;
X	return SRCH_ABORT;
X    }
X#ifdef KILLFILES
X    if (saltaway) {
X	char saltbuf[LBUFLEN];
X
X	s = saltbuf;
X	sprintf(s,"/%s/",pattern);
X	s += strlen(s);
X	if (doread)
X	    *s++ = 'r';
X	if (howmuch==1)
X	    *s++ = 'h';
X	else if (howmuch==2)
X	    *s++ = 'a';
X	*s++ = ':';
X	if (!cmdlst)
X	    cmdlst = savestr("j");
X	safecpy(s,cmdlst,LBUFLEN-(s-saltbuf));
X	kf_append(saltbuf);
X    }
X#endif
X    if (cmdlst && index(cmdlst,'='))
X	normal_return = SRCH_ERROR;	/* listing subjects is an error? */
X    if (get_cmd) {
X	fputs("\nSearching...\n",stdout) FLUSH;
X					/* give them something to read */
X    }
X#ifdef USETHREADS
X    if (mode == 't') {
X	if (!cmdlst)
X	    cmdlst = savestr("+");	/* thread selector's default command */
X	if (unread_selector)
X	    doread = TRUE;
X	normal_return = SRCH_DONE;
X    }
X#endif
X    if (backward) {
X	if (cmdlst && art <= lastart)
X	    art++;			/* include current article */
X	if (doread)
X	    check_first(absfirst);
X    }
X    else {
X	if (art > lastart) {
X	    art = (doread ? absfirst : firstart);
X	    check_first(art--);
X	}
X	else if (cmdlst && art >= absfirst)
X	    art--;			/* include current article */
X    }
X    if (srchahead > 0) {
X	if (!backward)
X	    art = srchahead - 1;
X	srchahead = -1;
X    }
X    assert(!cmdlst || *cmdlst);
X    perform_cnt = 0;
X    for (;;) {
X	if (backward ?
X		(--art < absfirst || (!doread && art < firstart)) :
X		(++art > lastart)
X	  ) {			/* out of articles? */
X	    if (cmdlst)
X		free(cmdlst);
X	    return normal_return;
X	}
X	if (int_count) {
X	    int_count = 0;
X	    if (cmdlst)
X		free(cmdlst);
X	    return SRCH_INTR;
X	}
X	/*NOSTRICT*/
X	if (doread || !was_read(art)) {
X	    if (wanted(compex,art,howmuch)) {
X				    /* does the shoe fit? */
X		if (cmdlst) {
X		    if (perform(cmdlst,TRUE)) {
X			if (cmdlst)
X			    free(cmdlst);
X			return SRCH_INTR;
X		    }
X		}
X		else {
X		    if (cmdlst)
X			free(cmdlst);
X		    return SRCH_FOUND;
X		}
X	    }
X	    else if (!cmdlst && ! (art%50)) {
X		printf("...%ld",(long)art);
X		fflush(stdout);
X	    }
X	}
X    }
X}
X
X/* determine if article fits pattern */
X/* returns TRUE if it exists and fits pattern, FALSE otherwise */
X
Xbool
Xwanted(compex, artnum, scope)
XCOMPEX *compex;
XART_NUM artnum;
Xchar scope;
X{
X    if (!scope) {
X	char subj_buf[266];
X	
X#ifdef USETHREADS
X	if (ThreadedGroup)
X	    find_article(art);
X	if (p_art) {
X	    if (mode != 't')
X		strcpy(subj_buf, "Subject: ");
X	    else
X		*subj_buf = '\0';
X	    if (p_art->subject != -1)
X		strcat(subj_buf,subject_ptrs[p_art->subject]);
X	}
X	else
X#endif
X	{
X	    strcpy(subj_buf, "Subject: ");
X	    strncpy(subj_buf+9,fetchsubj(artnum,FALSE,FALSE),256);
X	}
X#ifdef DEBUGGING
X	if (debug & DEB_SEARCH_AHEAD)
X	    printf("%s\n",subj_buf) FLUSH;
X#endif
X	return execute(compex,subj_buf) != Nullch;
X    }
X#ifdef CACHESUBJ
X    else
X	fetchsubj(artnum,FALSE,FALSE);/* might as well get subject handy */
X#endif
X    
X#ifdef SERVER
X    if (scope == 1){
X	if (nntpopen(artnum,GET_HEADER) == Nullfp) /* we only need the header */
X	    return FALSE;
X    }
X    else
X#endif
X    if (artopen(artnum) == Nullfp)	/* ensure that article is open */
X
X	return FALSE;			/* if not, return NO MATCH */
X    scope--;
X    while (fgets(buf,LBUFLEN,artfp) != Nullch) {
X					/* for each line of article */
X	if (!scope && index(buf,':') == Nullch && *buf != ' ' && *buf != '\t')
X					/* if headers only and out of header */
X	    return FALSE;		/* say no go */
X	if (execute(compex,buf) != Nullch) {
X					/* does pattern matcher match? */
X	    return TRUE;		/* say Eureka */
X	}
X    }
X    return FALSE;			/* out of article, so no match */
X}
X#endif
X
SHAR_EOF
chmod 0660 artsrch.c || echo "restore of artsrch.c fails"
echo "x - extracting artsrch.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > artsrch.h &&
X/* $Header: artsrch.h,v 4.3 85/05/01 11:35:55 lwall Exp $
X *
X * $Log:	artsrch.h,v $
X * Revision 4.3  85/05/01  11:35:55  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
X#ifndef NBRA
X#include "search.h"
X#endif
X
X#ifdef ARTSEARCH
X
X#define SRCH_ABORT 0
X#define SRCH_INTR 1
X#define SRCH_FOUND 2
X#define SRCH_NOTFOUND 3
X#define SRCH_DONE 4
X#define SRCH_SUBJDONE 5
X#define SRCH_ERROR 6
X#endif
X
XEXT char *lastpat INIT(nullstr);	/* last search pattern */
X#ifdef ARTSEARCH
X    EXT COMPEX sub_compex;		/* last compiled subject search */
X    EXT COMPEX art_compex;		/* last compiled normal search */
X#   ifdef CONDSUB
X	EXT COMPEX *bra_compex INIT(&art_compex);
X					/* current compex with brackets */
X#   endif
X    EXT char art_howmuch;		/* search just the subjects */
X    EXT bool art_doread;		/* search read articles? */
X#endif
X
Xvoid	artsrch_init();
X#ifdef ARTSEARCH
X    int		art_search();
X    bool	wanted();	/* return TRUE if current article matches pattern */
X#endif
SHAR_EOF
chmod 0660 artsrch.h || echo "restore of artsrch.h fails"
echo "x - extracting artstate.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > artstate.h &&
X/* $Header: artstate.h,v 4.3.1.2 85/05/13 09:30:30 lwall Exp $
X *
X * $Log:	artstate.h,v $
X * Revision 4.3.1.2  85/05/13  09:30:30  lwall
X * Added CUSTOMLINES option.
X * 
X * Revision 4.3.1.1  85/05/10  11:31:32  lwall
X * Branch for patches.
X * 
X * Revision 4.3  85/05/01  11:35:59  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
XEXT bool reread INIT(FALSE);		/* consider current art temporarily */
X				    /* unread? */
XEXT bool do_fseek INIT(FALSE);	/* should we back up in article file? */
X
XEXT bool oldsubject INIT(FALSE);	/* not 1st art in subject thread */
XEXT ART_LINE topline INIT(-1);		/* top line of current screen */
XEXT bool do_hiding INIT(TRUE);		/* hide header lines with -h? */
X#ifdef ROTATION
XEXT bool rotate INIT(FALSE);		/* has rotation been requested? */
X#endif
XEXT char *prompt;			/* pointer to current prompt */
X
XEXT char *firstline INIT(Nullch);			/* special first line? */
X#ifdef CUSTOMLINES
XEXT char *hideline INIT(Nullch);		/* custom line hiding? */
XEXT char *pagestop INIT(Nullch);		/* custom page terminator? */
XEXT COMPEX hide_compex;
XEXT COMPEX page_compex;
X#endif
SHAR_EOF
chmod 0660 artstate.h || echo "restore of artstate.h fails"
echo "x - extracting backpage.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > backpage.c &&
X/* $Header: backpage.c,v 4.3.3.1 90/06/20 22:36:17 davison Trn $
X *
X * $Log:	backpage.c,v $
X * Revision 4.3.3.1  90/06/20  22:36:17  davison
X * Initial Trn Release
X * 
X * Revision 4.3  85/05/01  11:36:03  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "intrp.h"
X#include "final.h"
X#include "INTERN.h"
X#include "backpage.h"
X
XART_LINE maxindx = -1;
Xlong lseek();
X
Xvoid
Xbackpage_init()
X{
X    char *varyname;
X    
X    varyname = filexp(VARYNAME);
X    close(creat(varyname,0600));
X    varyfd = open(varyname,2);
X    UNLINK(varyname);
X    if (varyfd < 0) {
X	printf(cantopen,varyname) FLUSH;
X	sig_catcher(0);
X    }
X    
X}
X
X/* virtual array read */
X
XART_POS
Xvrdary(indx)
XART_LINE indx;
X{
X    int subindx;
X    long offset;
X
X#ifdef DEBUGGING
X    if (indx > maxindx) {
X	printf("vrdary(%ld) > %ld\n",(long)indx, (long)maxindx) FLUSH;
X	return 0;
X    }
X#endif
X    if (indx < 0)
X	return 0;
X    subindx = indx % VARYSIZE;
X    offset = (indx - subindx) * sizeof(varybuf[0]);
X    if (offset != oldoffset) {
X	if (oldoffset >= 0) {
X#ifndef lint
X	    (void)lseek(varyfd,oldoffset,0);
X	    write(varyfd, (char *)varybuf,sizeof(varybuf));
X#endif /* lint */
X	}
X#ifndef lint
X	(void)lseek(varyfd,offset,0);
X	read(varyfd,(char *)varybuf,sizeof(varybuf));
X#endif /* lint */
X	oldoffset = offset;
X    }
X    return varybuf[subindx];
X}
X
X/* write to virtual array */
X
Xvoid
Xvwtary(indx,newvalue)
XART_LINE indx;
XART_POS newvalue;
X{
X    int subindx;
X    long offset;
X
X#ifdef DEBUGGING
X    if (indx < 0)
X	printf("vwtary(%ld)\n",(long)indx) FLUSH;
X    if (!indx)
X	maxindx = 0;
X    if (indx > maxindx) {
X	if (indx != maxindx + 1)
X	    printf("indx skipped %d-%d\n",maxindx+1,indx-1) FLUSH;
X	maxindx = indx;
X    }
X#endif
X    subindx = indx % VARYSIZE;
X    offset = (indx - subindx) * sizeof(varybuf[0]);
X    if (offset != oldoffset) {
X	if (oldoffset >= 0) {
X#ifndef lint
X	    (void)lseek(varyfd,oldoffset,0);
X	    write(varyfd,(char *)varybuf,sizeof(varybuf));
X#endif /* lint */
X	}
X#ifndef lint
X	(void)lseek(varyfd,offset,0);
X	read(varyfd,(char *)varybuf,sizeof(varybuf));
X#endif /* lint */
X	oldoffset = offset;
X    }
X    varybuf[subindx] = newvalue;
X}
X
SHAR_EOF
chmod 0660 backpage.c || echo "restore of backpage.c fails"
echo "x - extracting backpage.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > backpage.h &&
X/* $Header: backpage.h,v 4.3 85/05/01 11:36:11 lwall Exp $
X *
X * $Log:	backpage.h,v $
X * Revision 4.3  85/05/01  11:36:11  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
X/* things for doing the 'back page' command */
X
XEXT int varyfd INIT(0);			/* virtual array file for storing  */
X					/* file offsets */
XEXT ART_POS varybuf[VARYSIZE];		/* current window onto virtual array */
X
XEXT long oldoffset INIT(-1);		/* offset to block currently in window */
X
Xvoid	backpage_init();
XART_POS	vrdary();
Xvoid	vwtary();
SHAR_EOF
chmod 0660 backpage.h || echo "restore of backpage.h fails"
echo "x - extracting bits.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > bits.c &&
X/* $Header: bits.c,v 4.3.3.1 90/06/20 22:36:24 davison Trn $
X *
X * $Log:	bits.c,v $
X * Revision 4.3.3.1  90/06/20  22:36:24  davison
X * Initial Trn Release
X * 
X * Revision 4.3.2.3  89/11/28  01:52:02  sob
X * Removed some lint.
X * 
X * Revision 4.3.2.2  89/11/27  01:30:04  sob
X * Altered NNTP code per ideas suggested by Bela Lubkin
X * <filbo at gorn.santa-cruz.ca.us>
X * 
X * Revision 4.3.1.4  86/10/31  15:23:53  lwall
X * Separated firstart into two variables so KILL on new articles won't
X * accidentally mark articles read.
X * 
X * Revision 4.3.1.3  86/09/09  16:01:43  lwall
X * Fixed 'n more articles' bug.
X * 
X * Revision 4.3.1.2  86/07/24  14:40:23  lwall
X * Gets host name from path instead of relay-version for news 2.10.3.
X *
X * Revision 4.3.1.1  85/05/10  11:31:41  lwall
X * Branch for patches.
X *
X * Revision 4.3  85/05/01  11:36:15  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "rcstuff.h"
X#include "head.h"
X#include "util.h"
X#include "final.h"
X#include "rn.h"
X#include "cheat.h"
X#include "ng.h"
X#include "artio.h"
X#include "intrp.h"
X#include "ngdata.h"
X#include "rcln.h"
X#include "kfile.h"
X#ifdef USETHREADS
X#include "rthreads.h"
X#endif
X#include "INTERN.h"
X#include "bits.h"
X
X#ifdef DBM
X#    ifdef NULL
X#	undef NULL
X#    endif
X#    include <dbm.h>
X#endif
XMEM_SIZE ctlsize;			/* size of bitmap in bytes */
X
Xvoid
Xbits_init()
X{
X#ifdef DELAYMARK
X    dmname = savestr(filexp(RNDELNAME));
X#else
X    ;
X#endif
X}
X
X/* checkpoint the .newsrc */
X
Xvoid
Xcheckpoint_rc()
X{
X#ifdef DEBUGGING
X    if (debug & DEB_CHECKPOINTING) {
X	fputs("(ckpt)",stdout);
X	fflush(stdout);
X    }
X#endif
X    if (doing_ng)
X	restore_ng();			/* do not restore M articles */
X    if (rc_changed)
X	write_rc();
X#ifdef DEBUGGING
X    if (debug & DEB_CHECKPOINTING) {
X	fputs("(done)",stdout);
X	fflush(stdout);
X    }
X#endif
X}
X
X/* reconstruct the .newsrc line in a human readable form */
X
Xvoid
Xrestore_ng()
X{
X    register char *s, *mybuf = buf;
X    register ART_NUM i;
X    ART_NUM count=0;
X    int safelen = LBUFLEN - 16;
X
X    strcpy(buf,rcline[ng]);		/* start with the newsgroup name */
X    s = buf + rcnums[ng] - 1;		/* use s for buffer pointer */
X    *s++ = rcchar[ng];			/* put the requisite : or !*/
X    *s++ = ' ';				/* put the not-so-requisite space */
X    for (i=1; i<=lastart; i++) {	/* for each article in newsgroup */
X	if (s-mybuf > safelen) {	/* running out of room? */
X	    safelen *= 2;
X	    if (mybuf == buf) {		/* currently static? */
X		*s = '\0';
X		mybuf = safemalloc((MEM_SIZE)safelen + 16);
X		strcpy(mybuf,buf);	/* so we must copy it */
X		s = mybuf + (s-buf);
X					/* fix the pointer, too */
X	    }
X	    else {			/* just grow in place, if possible */
X		char *newbuf;
X
X		newbuf = saferealloc(mybuf,(MEM_SIZE)safelen + 16);
X		s = newbuf + (s-mybuf);
X		mybuf = newbuf;
X	    }
X	}
X	if (!was_read(i))		/* still unread? */
X	    count++;			/* then count it */
X	else {				/* article was read */
X	    ART_NUM oldi;
X
X	    sprintf(s,"%ld",(long)i);	/* put out the min of the range */
X	    s += strlen(s);		/* keeping house */
X	    oldi = i;			/* remember this spot */
X	    do i++; while (i <= lastart && was_read(i));
X					/* find 1st unread article or end */
X	    i--;			/* backup to last read article */
X	    if (i > oldi) {		/* range of more than 1? */
X		sprintf(s,"-%ld,",(long)i);
X					/* then it out as a range */
X		s += strlen(s);		/* and housekeep */
X	    }
X	    else
X		*s++ = ',';		/* otherwise, just a comma will do */
X	}
X    }
X    if (*(s-1) == ',')			/* is there a final ','? */
X	s--;				/* take it back */
X    *s++ = '\0';			/* and terminate string */
X#ifdef DEBUGGING
X    if (debug & DEB_NEWSRC_LINE && !panic) {
X	printf("%s: %s\n",rcline[ng],rcline[ng]+rcnums[ng]) FLUSH;
X	printf("%s\n",mybuf) FLUSH;
X    }
X#endif
X    free(rcline[ng]);			/* return old rc line */
X    if (mybuf == buf) {
X	rcline[ng] = safemalloc((MEM_SIZE)(s-buf)+1);
X					/* grab a new rc line */
X	strcpy(rcline[ng], buf);	/* and load it */
X    }
X    else {
X	mybuf = saferealloc(mybuf,(MEM_SIZE)(s-mybuf)+1);
X					/* be nice to the heap */
X	rcline[ng] = mybuf;
X    }
X    *(rcline[ng] + rcnums[ng] - 1) = '\0';
X    if (rcchar[ng] == NEGCHAR) {	/* did they unsubscribe? */
X	printf(unsubto,ngname) FLUSH;
X	toread[ng] = TR_UNSUB;		/* make line invisible */
X    }
X    else
X	/*NOSTRICT*/
X	toread[ng] = (ART_UNREAD)count;		/* remember how many unread there are */
X}
X
X/* mark an article unread, keeping track of toread[] */
X
Xvoid
Xonemore(artnum)
XART_NUM artnum;
X{
X#ifdef DEBUGGING
X    if (debug && artnum < firstbit) {
X	printf("onemore: %d < %d\n",artnum,firstbit) FLUSH;
X	return;
X    }
X#endif
X    if (ctl_read(artnum)) {
X	ctl_clear(artnum);
X	++toread[ng];
X    }
X}
X
X/* mark an article read, keeping track of toread[] */
X
Xvoid
Xoneless(artnum)
XART_NUM artnum;
X{
X#ifdef DEBUGGING
X    if (debug && artnum < firstbit) {
X	printf("oneless: %d < %d\n",artnum,firstbit) FLUSH;
X	return;
X    }
X#endif
X    if (!ctl_read(artnum)) {
X	ctl_set(artnum);
X	if (toread[ng] > TR_NONE)
X	    --toread[ng];
X    }
X}
X
X/* mark an article as unread, making sure that firstbit is properly handled */
X/* cross-references are left as read in the other newsgroups */
X
Xvoid
Xunmark_as_read()
X{
X    check_first(art);
X#ifdef USETHREADS
X    /* Keep selected_count accurate */
X    if (ctl_read(art)) {
X	find_article(art);
X	if (p_art) {
X	    if (selected_roots[p_art->root]) {
X		selected_count++;
X	    }
X	    root_article_cnts[p_art->root] = 1;
X	} else
X	    unthreaded++;
X    }
X    scan_all_roots = FALSE;
X#endif
X    onemore(art);
X#ifdef MCHASE
X    if (!parse_maybe(art))
X	chase_xrefs(art,FALSE);
X#endif
X}
X
X#ifdef USETHREADS
X/* mark an article as read in this newsgroup only */
X
Xvoid
Xset_read(artnum,sel)
XART_NUM artnum;
Xint sel;
X{
X    if (!ctl_read(artnum)) {
X	oneless(artnum);
X	if( p_art->subject != -1 )
X	    selected_count -= sel;
X    }
X}
X
X/* mark an article as unread in this newsgroup only */
X
Xvoid
Xset_unread(artnum,sel)
XART_NUM artnum;
Xint sel;
X{
X    if (artnum >= absfirst) {
X	check_first(artnum);
X	if (ctl_read(artnum)) {
X	    onemore(artnum);
X	    selected_count += sel;
X	    root_article_cnts[p_art->root] = 1;
X	    scan_all_roots = FALSE;
X	}
X    }
X}
X#endif
X
X#ifdef DELAYMARK
X/* temporarily mark article as read.  When newsgroup is exited, articles */
X/* will be marked as unread.  Called via M command */
X
Xvoid
Xdelay_unmark(artnum)
XART_NUM artnum;
X{
X    if (dmfp == Nullfp) {
X	dmfp = fopen(dmname,"w+");
X	if (dmfp == Nullfp) {
X	    printf(cantcreate,dmname) FLUSH;
X	    sig_catcher(0);
X	}
X    }
X#ifdef USETHREADS
X    /* Keep selected_count accurate */
X    if (!ctl_read(artnum)) {
X	find_article(artnum);
X	if (p_art) {
X	    if (selected_roots[p_art->root])
X		selected_count--;
X	} else
X	    unthreaded--;
X    }
X#endif
X    oneless(artnum);			/* set the correct bit */
X    dmcount++;
X    fprintf(dmfp,"%ld\n",(long)artnum);
X}
X#endif
X
X/* mark article as read.  If article is cross referenced to other */
X/* newsgroups, mark them read there also. */
X
Xvoid
Xmark_as_read()
X{
X#ifdef USETHREADS
X    /* Keep selected_count accurate */
X    if (!ctl_read(art)) {
X	find_article(art);
X	if (p_art) {
X	    if (selected_roots[p_art->root])
X		selected_count--;
X	} else
X	    unthreaded--;
X    }
X#endif
X    oneless(art);			/* set the correct bit */
X    checkcount++;			/* get more worried about crashes */
X    chase_xrefs(art,TRUE);
X}
X
X/* make sure we have bits set correctly down to firstbit */
X
Xvoid
Xcheck_first(min)
XART_NUM min;
X{
X    register ART_NUM i = firstbit;
X
X    if (min < absfirst)
X	min = absfirst;
X    if (min < i) {
X	for (i--; i>=min; i--)
X	    ctl_set(i);		/* mark as read */
X	firstart = firstbit = min;
X    }
X}
X
X/* bring back articles marked with M */
X
X#ifdef DELAYMARK
Xvoid
Xyankback()
X{
X    if (dmfp) {			/* delayed unmarks pending? */
X#ifdef VERBOSE
X	printf("\nReturning %ld Marked article%s...\n",(long)dmcount,
X	    dmcount == 1 ? nullstr : "s") FLUSH;
X#endif
X	rewind(dmfp);
X	while (fgets(buf,sizeof buf,dmfp) != Nullch) {
X	    art = (ART_NUM)atol(buf);
X	    unmark_as_read();
X	}
X	fclose(dmfp);
X	dmfp = Nullfp;
X	UNLINK(dmname);		/* and be tidy */
X    }
X    dmcount = 0;
X}
X#endif
X    
X/* run down xref list and mark as read or unread */
X
Xint
Xchase_xrefs(artnum,markread)
XART_NUM artnum;
Xint markread;
X{
X#ifdef ASYNC_PARSE
X    if (parse_maybe(artnum))		/* make sure we have right header */
X	return -1;
X#endif
X#ifdef DBM
X    {
X	datum lhs, rhs;
X	datum fetch();
X	register char *idp;
X	char *ident_buf;
X	static FILE * hist_file = Nullfp;
X#else
X    if (
X#ifdef DEBUGGING
X	debug & DEB_FEED_XREF ||
X#endif
X	htype[XREF_LINE].ht_minpos >= 0) {
X					/* are there article# xrefs? */
X#endif /* DBM */
X	char *xref_buf, *curxref;
X	register char *xartnum;
X	char *rver_buf = Nullch;
X	static char *inews_site = Nullch;
X	register ART_NUM x;
X	char tmpbuf[128];
X
X#ifdef DBM
X	rver_buf = fetchlines(artnum,NGS_LINE);
X					/* get Newsgroups */
X	if (!index(rver_buf,','))	/* if no comma, no Xref! */
X	    return 0;
X	if (hist_file == Nullfp) {	/* Init. file accesses */
X#ifdef DEBUGGING
X	    if (debug)
X		printf ("chase_xref: opening files\n");
X#endif
X	    dbminit(filexp(ARTFILE));
X	    if ((hist_file = fopen (filexp(ARTFILE), "r")) == Nullfp)
X		return 0;
X	}
X	xref_buf = safemalloc((MEM_SIZE)BUFSIZ);
X	ident_buf = fetchlines(artnum,MESSID_LINE);
X					/* get Message-ID */
X#ifdef DEBUGGING
X	if (debug)
X	    printf ("chase_xref: Message-ID: %s\n", ident_buf);
X#endif
X	idp = ident_buf;
X	while (*++idp)			/* make message-id case insensitive */
X	    if (isupper(*idp))
X	        *idp = tolower (*idp);
X	lhs.dptr = ident_buf;		/* look up article by id */
X	lhs.dsize = strlen(lhs.dptr) + 1;
X	rhs = fetch(lhs);		/* fetch the record */
X	if (rhs.dptr == NULL)		/* if null, nothing there */
X	    goto wild_goose;
X	fseek (hist_file, *((long *)rhs.dptr), 0);
X					/* datum returned is position in hist file */
X	fgets (xref_buf, BUFSIZ, hist_file);
X#ifdef DEBUGGING
X	if (debug)
X	    printf ("Xref from history: %s\n", xref_buf);
X#endif
X	curxref = cpytill(tmpbuf, xref_buf, '\t') + 1;
X	curxref = cpytill(tmpbuf, curxref, '\t') + 1;
X#ifdef DEBUGGING
X	if (debug)
X	    printf ("chase_xref: curxref: %s\n", curxref);
X#endif
X#else /* !DBM */
X#ifdef DEBUGGING
X	if (htype[XREF_LINE].ht_minpos >= 0)
X#endif
X	    xref_buf = fetchlines(artnum,XREF_LINE);
X					/* get xrefs list */
X#ifdef DEBUGGING
X	else {
X	    xref_buf = safemalloc((MEM_SIZE)100);
X	    printf("Give Xref: ") FLUSH;
X	    gets(xref_buf);
X	}
X#endif
X#ifdef DEBUGGING
X	if (debug & DEB_XREF_MARKER)
X	    printf("Xref: %s\n",xref_buf) FLUSH;
X#endif
X	curxref = cpytill(tmpbuf,xref_buf,' ') + 1;
X
X	/* Make sure site name on Xref matches what inews thinks site is.
X	 * Check first against last inews_site.  If it matches, fine.
X	 * If not, fetch inews_site from current Relay-Version line and
X	 * check again.  This is so that if the new administrator decides
X	 * to change the system name as known to inews, rn will still do
X	 * Xrefs correctly--each article need only match itself to be valid.
X	 */ 
X	if (inews_site == Nullch || strNE(tmpbuf,inews_site)) {
X#ifndef NORELAY
X	    char *t;
X#endif
X	    if (inews_site != Nullch)
X		free(inews_site);
X#ifndef NORELAY
X	    rver_buf = fetchlines(artnum,RVER_LINE);
X	    if ((t = instr(rver_buf,"; site ")) == Nullch)
X#else /* NORELAY */
X          /* In version 2.10.3 of news or afterwards, the Relay-Version
X           * and Posting-Version header lines have been removed.  For
X           * the code below to work as intended, I have modified it to
X           * extract the first component of the Path header line.  This
X           * should give the same effect as did the old code with respect
X           * to the use of the Relay-Version site name.
X           */
X          rver_buf = fetchlines(artnum,PATH_LINE);
X          if (instr(rver_buf,"!") == Nullch)
X#endif /* NORELAY */
X		inews_site = savestr(nullstr);
X	    else {
X		char new_site[128];
X
X#ifndef NORELAY
X		cpytill(new_site,t + 7,'.');
X#else /* NORELAY */
X              cpytill(new_site,rver_buf,'!');
X#endif /* NORELAY */
X		inews_site = savestr(new_site);
X	    }
X	    if (strNE(tmpbuf,inews_site)) {
X#ifdef DEBUGGING
X		if (debug)
X		    printf("Xref not from %s--ignoring\n",inews_site) FLUSH;
X#endif
X		goto wild_goose;
X	    }
X	}
X#endif /* DBM */
X	while (*curxref) {
X					/* for each newsgroup */
X	    curxref = cpytill(tmpbuf,curxref,' ');
X#ifdef DBM
X	    xartnum = index(tmpbuf,'/');
X#else
X	    xartnum = index(tmpbuf,':');
X#endif /* DBM */
X	    if (!xartnum)		/* probably an old-style Xref */
X		break;
X	    *xartnum++ = '\0';
X	    if (strNE(tmpbuf,ngname)) {/* not the current newsgroup? */
X		x = atol(xartnum);
X		if (x)
X		    if (markread) {
X			if (addartnum(x,tmpbuf))
X			    goto wild_goose;
X		    }
X#ifdef MCHASE
X		    else
X			subartnum(x,tmpbuf);
X#endif
X	    }
X	    while (*curxref && isspace(*curxref))
X		curxref++;
X	}
X      wild_goose:
X	free(xref_buf);
X#ifdef DBM
X	free(ident_buf);
X#endif /* DBM */
X	if (rver_buf != Nullch)
X	    free(rver_buf);
X    }
X    return 0;
X}
X
Xint
Xinitctl()
X{
X    char *mybuf = buf;			/* place to decode rc line */
X    register char *s, *c, *h;
X    register long i;
X    register ART_NUM unread;
X    
X#ifdef DELAYMARK
X    dmcount = 0;
X#endif
X    if ((lastart = getngsize(ng)) < 0)	/* this cannot happen (laugh here) */
X	return -1;
X
X    absfirst = getabsfirst(ng,lastart);	/* remember first existing article */
X    if (!absfirst)			/* no articles at all? */
X	absfirst = 1;			/* pretend there is one */
X#ifndef lint
X    ctlsize = (MEM_SIZE)(OFFSET(lastart)/BITSPERBYTE+20);
X#endif /* lint */
X    ctlarea = safemalloc(ctlsize);	/* allocate control area */
X
X    /* now modify ctlarea to reflect what has already been read */
X
X    for (s = rcline[ng] + rcnums[ng]; *s == ' '; s++) ;
X					/* find numbers in rc line */
X    i = strlen(s);
X#ifndef lint
X    if (i >= LBUFLEN-2)			/* bigger than buf? */
X	mybuf = safemalloc((MEM_SIZE)(i+2));
X#endif /* lint */
X    strcpy(mybuf,s);			/* make scratch copy of line */
X    mybuf[i++] = ',';			/* put extra comma on the end */
X    mybuf[i] = '\0';
X    s = mybuf;				/* initialize the for loop below */
X    if (strnEQ(s,"1-",2)) {		/* can we save some time here? */
X	firstbit = atol(s+2)+1;		/* ignore first range thusly */
X	s=index(s,',') + 1;
X    }
X    else
X	firstbit = 1;			/* all the bits are valid for now */
X    if (absfirst > firstbit) {		/* do we know already? */
X	firstbit = absfirst;		/* no point calling getngmin again */
X    }
X    else if (artopen(firstbit) == Nullfp) {
X					/* first unread article missing? */
X	i = getngmin(".",firstbit);	/* see if expire has been busy */
X	if (i) {			/* avoid a bunch of extra opens */
X	    firstbit = i;
X	}
X    }
X    firstart = firstbit;		/* firstart > firstbit in KILL */
X#ifdef PENDING
X#   ifdef CACHESUBJ
X	subj_to_get = firstbit;
X#   endif
X#endif
X    unread = lastart - firstbit + 1;	/* assume this range unread */
X    for (i=OFFSET(firstbit)/BITSPERBYTE; i<ctlsize; i++)
X	ctlarea[i] = 0;			/* assume unread */
X#ifdef DEBUGGING
X    if (debug & DEB_CTLAREA_BITMAP) {
X	printf("\n%s\n",mybuf) FLUSH;
X	for (i=1; i <= lastart; i++)
X	    if (! was_read(i))
X		printf("%ld ",(long)i) FLUSH;
X    }
X#endif
X    for ( ; (c = index(s,',')) != Nullch; s = ++c) {
X					/* for each range */
X	ART_NUM min, max;
X
X	*c = '\0';			/* do not let index see past comma */
X	if ((h = index(s,'-')) != Nullch) {	/* is there a -? */
X	    min = atol(s);
X	    max = atol(h+1);
X	    if (min < firstbit)		/* make sure range is in range */
X		min = firstbit;
X	    if (max > lastart)
X		max = lastart;
X	    if (min <= max)		/* non-null range? */
X		unread -= max - min + 1;/* adjust unread count */
X	    for (i=min; i<=max; i++)	/* for all articles in range */
X		ctl_set(i);		/* mark them read */
X	}
X	else if ((i = atol(s)) >= firstbit && i <= lastart) {
X					/* is single number reasonable? */
X	    ctl_set(i);			/* mark it read */
X	    unread--;			/* decrement articles to read */
X	}
X#ifdef DEBUGGING
X	if (debug & DEB_CTLAREA_BITMAP) {
X	    printf("\n%s\n",s) FLUSH;
X	    for (i=1; i <= lastart; i++)
X		if (! was_read(i))
X		    printf("%ld ",(long)i) FLUSH;
X	}
X#endif
X    }
X#ifdef DEBUGGING
X    if (debug & DEB_CTLAREA_BITMAP) {
X	fputs("\n(hit CR)",stdout) FLUSH;
X	gets(cmd_buf);
X    }
X#endif
X    if (mybuf != buf)
X	free(mybuf);
X    toread[ng] = unread;
X    return 0;
X}
X
Xvoid
Xgrow_ctl(newlast)
XART_NUM newlast;
X{
X    ART_NUM tmpfirst;
X    MEM_SIZE newsize;
X    register ART_NUM i;
X
X    forcegrow = FALSE;
X    if (newlast > lastart) {
X	ART_NUM tmpart = art;
X#ifndef lint
X	newsize = (MEM_SIZE)(OFFSET(newlast)/BITSPERBYTE+2);
X#else
X	newsize = Null(MEM_SIZE);
X#endif /* lint */
X	if (newsize > ctlsize) {
X	    newsize += 20;
X	    ctlarea = saferealloc(ctlarea,newsize);
X	    ctlsize = newsize;
X	}
X	toread[ng] += (ART_UNREAD)(newlast-lastart);
X	for (i=lastart+1; i<=newlast; i++)
X	    ctl_clear(i);	/* these articles are unread */
X#ifdef CACHESUBJ
X	if (subj_list != Null(char**)) {
X#ifndef lint
X	    subj_list = (char**)saferealloc((char*)subj_list,
X		  (MEM_SIZE)((OFFSET(newlast)+2)*sizeof(char *)) );
X#endif /* lint */
X	    for (i=lastart+1; i<=newlast; i++)
X		subj_list[OFFSET(i)] = Nullch;
X	}
X#endif
X	tmpfirst = lastart+1;
X	lastart = newlast;
X#ifdef KILLFILES
X#ifdef VERBOSE
X	IF(verbose)
X	    sprintf(buf,
X		"%ld more article%s arrived--looking for more to kill...\n\n",
X		(long)(lastart - tmpfirst + 1),
X		(lastart > tmpfirst ? "s have" : " has" ) );
X	ELSE			/* my, my, how clever we are */
X#endif
X#ifdef TERSE
X	    strcpy(buf, "More news--killing...\n\n");
X#endif
X	kill_unwanted(tmpfirst,buf,TRUE);
X#endif
X	art = tmpart;
X    }
X}
X
SHAR_EOF
chmod 0660 bits.c || echo "restore of bits.c fails"
echo "x - extracting bits.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > bits.h &&
X/* $Header: bits.h,v 4.3.3.1 90/06/20 22:36:35 davison Trn $
X *
X * $Log:	bits.h,v $
X * Revision 4.3.3.1  90/06/20  22:36:35  davison
X * Initial Trn Release
X * 
X * Revision 4.3.1.2  86/11/03  09:49:58  lwall
X * Added firstbit variable.
X * 
X * Revision 4.3.1.1  85/05/10  11:31:52  lwall
X * Branch for patches.
X * 
X * Revision 4.3  85/05/01  11:36:39  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
XEXT char *ctlarea INIT(Nullch);	/* one bit for each article in current newsgroup */
X			/* with the following interpretation: */
X			/*	0 => unread  */
X			/*	1 => read    */
X
X/* if subscripting is faster than shifting on your machine, define this */
X#undef USESUBSCRIPT
X#ifdef USESUBSCRIPT
XEXT char powerof2[] INIT({1,2,4,8,16,32,64,128});
X#define pow2(x) powerof2[x]
X#else
X#define pow2(x) (1 << (x))
X#endif
X
X#ifdef lint
XEXT bool nonesuch INIT(FALSE);
X#define ctl_set(a)
X#define ctl_clear(a)
X#define ctl_read(a) nonesuch
X#define was_read(a) nonesuch
X#else
X#define ctl_set(a) (ctlarea[(OFFSET(a)) / BITSPERBYTE] |= pow2((OFFSET(a)) % BITSPERBYTE))
X#define ctl_clear(a) (ctlarea[(OFFSET(a)) / BITSPERBYTE] &= ~pow2((OFFSET(a)) % BITSPERBYTE))
X#define ctl_read(a) ((ctlarea[(OFFSET(a)) / BITSPERBYTE] & pow2((OFFSET(a)) % BITSPERBYTE)) != 0)
X
X#define was_read(a) ((a)<firstbit || ctl_read(a))
X#endif /* lint */
X
XEXT ART_NUM absfirst INIT(0);	/* 1st real article in current newsgroup */
XEXT ART_NUM firstart INIT(0);	/* minimum unread article number in newsgroup */
XEXT ART_NUM firstbit INIT(0);	/* minimum valid bit, usually == firstart */
XEXT ART_NUM lastart INIT(0);	/* maximum article number in newsgroup */
X
X#ifdef DELAYMARK
XEXT FILE *dmfp INIT(Nullfp);
XEXT char *dmname INIT(Nullch);
XEXT int dmcount INIT(0);
X#endif
X
Xvoid	bits_init();
Xvoid	checkpoint_rc();
Xvoid	restore_ng();
Xvoid	onemore();
Xvoid	oneless();
Xvoid	unmark_as_read();
X#ifdef USETHREADS
Xvoid	set_read();
Xvoid	set_unread();
X#endif
Xvoid	delay_unmark();
Xvoid	mark_as_read();
Xvoid	check_first();
X#ifdef DELAYMARK
X    void	yankback();
X#endif
Xint	chase_xrefs();
Xint	initctl();
Xvoid	grow_ctl();
SHAR_EOF
chmod 0660 bits.h || echo "restore of bits.h fails"
echo "x - extracting cheat.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > cheat.c &&
X/* $Header: cheat.c,v 4.3.3.1 90/07/21 20:14:01 davison Trn $
X *
X * $Log:	cheat.c,v $
X * Revision 4.3.3.1  90/07/21  20:14:01  davison
X * Initial Trn Release
X * 
X * Revision 4.3.2.2  89/11/27  01:30:18  sob
X * Altered NNTP code per ideas suggested by Bela Lubkin
X * <filbo at gorn.santa-cruz.ca.us>
X * 
X * Revision 4.3.2.1  89/11/26  22:54:21  sob
X * Added RRN support
X * 
X * Revision 4.3  85/05/01  11:36:46  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "intrp.h"
X#include "search.h"
X#include "ng.h"
X#include "bits.h"
X#include "artio.h"
X#include "term.h"
X#include "artsrch.h"
X#include "head.h"
X#include "INTERN.h"
X#include "cheat.h"
X
X/* see what we can do while they are reading */
X
X#ifdef PENDING
X#   ifdef ARTSEARCH
X	COMPEX srchcompex;		/* compiled regex for searchahead */
X#   endif
X#endif
X
Xvoid
Xcheat_init()
X{
X    ;
X}
X
X#ifdef PENDING
Xvoid
Xlook_ahead()
X{
X#ifdef ARTSEARCH
X    register char *h, *s;
X
X#ifdef DEBUGGING
X    if (debug && srchahead) {
X	printf("(%ld)",(long)srchahead);
X	fflush(stdout);
X    }
X#endif
X    if (srchahead && srchahead < art) {	/* in ^N mode? */
X	char *pattern;
X
X	pattern = buf+1;
X	strcpy(pattern,": *");
X	h = pattern + strlen(pattern);
X	interp(h,(sizeof buf) - (h-buf),"%s");
X	h[24] = '\0';		/* compensate for notesfiles */
X	while (*h) {
X	    if (index("\\[.^*$'\"",*h) != Nullch)
X		*h++ = '.';
X	    else
X		h++;
X	}
X#ifdef DEBUGGING
X	if (debug & DEB_SEARCH_AHEAD) {
X	    fputs("(hit CR)",stdout);
X	    fflush(stdout);
X	    gets(buf+128);
X	    printf("\npattern = %s\n",pattern);
X	}
X#endif
X	if ((s = compile(&srchcompex,pattern,TRUE,TRUE)) != Nullch) {
X				    /* compile regular expression */
X	    printf("\n%s\n",s);
X	    srchahead = 0;
X	}
X	if (srchahead) {
X	    srchahead = art;
X	    for (;;) {
X		srchahead++;	/* go forward one article */
X		if (srchahead > lastart) { /* out of articles? */
X#ifdef DEBUGGING
X		    if (debug)
X			fputs("(not found)",stdout);
X#endif
X		    break;
X		}
X		if (!was_read(srchahead) &&
X		    wanted(&srchcompex,srchahead,0)) {
X				    /* does the shoe fit? */
X#ifdef DEBUGGING
X		    if (debug)
X			printf("(%ld)",(long)srchahead);
X#endif
X#ifdef SERVER
X		    nntpopen(srchahead,GET_HEADER);
X#else
X		    artopen(srchahead);
X#endif
X		    break;
X		}
X		if (input_pending())
X		    break;
X	    }
X	    fflush(stdout);
X	}
X    }
X    else
X#endif
X    {
X	if (art+1 <= lastart)/* how about a pre-fetch? */
X#ifdef SERVER
X	    nntpopen(art+1,GET_HEADER);	/* look for the next article */
X#else
X	    artopen(art+1);	/* look for the next article */
X#endif
X    }
X}
X#endif
X
X/* see what else we can do while they are reading */
X
Xvoid
Xcollect_subjects()
X{
X#ifdef PENDING
X# ifdef CACHESUBJ
X    ART_NUM oldart = openart;
X    ART_POS oldartpos;
X
X    if (!in_ng || !srchahead)
X	return;
X    if (oldart)			/* remember where we were in art */
X	oldartpos = ftell(artfp);
X    if (srchahead >= subj_to_get)
X	subj_to_get = srchahead+1;
X    while (!input_pending() && subj_to_get <= lastart)
X	fetchsubj(subj_to_get++,FALSE,FALSE);
X    if (oldart) {
X	artopen(oldart);
X	fseek(artfp,oldartpos,0);	/* do not screw the pager */
X    }
X# endif
X#endif
X}
X
SHAR_EOF
chmod 0660 cheat.c || echo "restore of cheat.c fails"
echo "x - extracting cheat.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > cheat.h &&
X/* $Header: cheat.h,v 4.3 85/05/01 11:36:58 lwall Exp $
X *
X * $Log:	cheat.h,v $
X * Revision 4.3  85/05/01  11:36:58  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
X#ifdef ARTSEARCH
XEXT ART_NUM srchahead INIT(0); 	/* are we in subject scan mode? */
X				/* (if so, contains art # found or -1) */
X#endif
X
X#ifdef PENDING
X#   ifdef CACHESUBJ
X	EXT ART_NUM subj_to_get;
X#   endif
X#endif
X
Xvoid	cheat_init();
Xvoid	look_ahead();
Xvoid	collect_subjects();
SHAR_EOF
chmod 0660 cheat.h || echo "restore of cheat.h fails"
echo "x - extracting common.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > common.h &&
X/* $Header: common.h,v 4.3.3.1 90/07/21 20:15:23 davison Trn $
X * 
X * $Log:	common.h,v $
X * Revision 4.3.3.1  90/07/21  20:15:23  davison
X * Initial Trn Release
X * 
X * Revision 4.3.2.13  90/05/08  22:05:37  sob
X * Added quick startup (-q) flag.
X * 
X * Revision 4.3.2.12  90/04/23  00:32:04  sob
X * More cleanup.
X * 
X * Revision 4.3.2.11  90/04/14  19:37:07  sob
X * Added better support for the NeXT.
X * 
X * Revision 4.3.2.10  90/04/06  20:54:12  sob
X * Corrected forward definition of fseek()
X * 
X * Revision 4.3.2.9  90/03/17  21:19:04  sob
X * Removed the incorrect forward definition of sprintf().
X * 
X * Revision 4.3.2.8  89/12/20  20:40:03  sob
X * Changed ACT_POS from short to long per suggestion from eps at cd.SFSU.EDU.
X * 
X * Revision 4.3.2.7  89/12/08  22:43:12  sob
X * Corrected typo pointed out by weening at gang-of-four.stanford.edu
X * 
X * Revision 4.3.2.6  89/11/28  01:57:31  sob
X * Added initlines_specified variable for use with SIGWINCH support.
X * 
X * Revision 4.3.2.5  89/11/28  00:30:56  sob
X * Reversed the CANCELHEADER definitions.
X * 
X * Revision 4.3.2.4  89/11/27  01:29:23  sob
X * Altered NNTP code per ideas suggested by Bela Lubkin
X * <filbo at gorn.santa-cruz.ca.us>
X * 
X * Revision 4.3.2.3  89/11/26  19:32:06  sob
X * Increased the size of MAXRCLINE from 1000 to 1500
X * Increated HASHSIZ from 1103 to 1693
X * 
X * Revision 4.3.2.2  89/11/07  23:18:49  sob
X * Repaired NEWSHEADER and CANCEL to work correctly with NNTP and INTERNET.
X * 
X * Revision 4.3.2.1  89/11/06  00:12:33  sob
X * Added RRN support from NNTP 1.5
X * 
X * Revision 4.3.1.4  86/10/31  15:46:09  lwall
X * Expanded maximum number of .newsrc lines for net reorganization.
X * 
X * Revision 4.3.1.3  85/05/23  17:19:32  lwall
X * Now allows 'r' and 'f' on null articles.
X * 
X * Revision 4.3.1.2  85/05/13  09:30:39  lwall
X * Added CUSTOMLINES option.
X * 
X * Revision 4.3.1.1  85/05/10  11:32:04  lwall
X * Branch for patches.
X * 
X * Revision 4.3  85/05/01  11:37:11  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
X#include "config.h"	/* generated by installation script */
X#ifdef WHOAMI
X#    include <whoami.h>
X#endif
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <ctype.h>
X
X#ifndef isalnum
X#   define isalnum(c) (isalpha(c) || isdigit(c))
X#endif
X
X#include <errno.h>
X#include <signal.h>
X#ifdef IOCTL
X#include <sys/ioctl.h>
X#endif
X
X#ifdef FCNTL
X#   include <fcntl.h>
X#endif
X
X#ifdef TERMIO
X#   include <termio.h>
X#else
X#   include <sgtty.h>
X#endif
X
X#ifdef GETPWENT
X#   include <pwd.h>
X#endif
X
X#define BITSPERBYTE 8
X#define LBUFLEN 512	/* line buffer length */
X			/* (don't worry, .newsrc lines can exceed this) */
X#ifdef pdp11
X#   define CBUFLEN 256	/* command buffer length */
X#   define PUSHSIZE 128
X#else
X#   define CBUFLEN 512	/* command buffer length */
X#   define PUSHSIZE 256
X#endif
X#ifdef pdp11
X#   define MAXFILENAME 128
X#else
X#   define MAXFILENAME 512
X#endif
X#define LONGKEY 15	/* longest keyword: currently "posting-version" */
X#define FINISHCMD 0177
X
X/* some handy defs */
X
X#define bool char
X#define TRUE (1)
X#define FALSE (0)
X#define Null(t) ((t)0)
X#define Nullch Null(char *)
X#define Nullfp Null(FILE *)
X
X#define Ctl(ch) (ch & 037)
X
X#define strNE(s1,s2) (strcmp(s1,s2))
X#define strEQ(s1,s2) (!strcmp(s1,s2))
X#define strnNE(s1,s2,l) (strncmp(s1,s2,l))
X#define strnEQ(s1,s2,l) (!strncmp(s1,s2,l))
X
X/* Things we can figure out ourselves */
X
X#ifdef SIGTSTP
X#   define BERKELEY 	/* include job control signals? */
X#endif
X
X#ifdef FIONREAD
X#   define PENDING
X#else
X#   ifdef O_NDELAY
X#	define PENDING
X#   endif
X#endif
X
X#ifdef EUNICE
X#   define LINKART		/* add 1 level of possible indirection */
X#   define UNLINK(victim) while (!unlink(victim))
X#else
X#   define UNLINK(victim) unlink(victim)
X#endif
X
X/* Valid substitutions for strings marked with % comment are:
X *	%a	Current article number
X *	%A	Full name of current article (%P/%c/%a)
X *		(if LINKART defined, is the name of the real article)
X *	%b	Destination of a save command, a mailbox or command
X *	%B	The byte offset to the beginning of the article for saves
X *		with or without the header
X *	%c	Current newsgroup, directory form
X *	%C	Current newsgroup, dot form
X *	%d	%P/%c
X *	%D	Old Distribution: line
X *	%f	Old From: line or Reply-To: line
X *	%F	Newsgroups to followup to from Newsgroups: and Followup-To:
X *	%h	Name of header file to pass to mail or news poster
X *	%H	Host name (yours)
X *	%i	Old Message-I.D.: line, with <>
X *	%I	Inclusion indicator
X *	%l	News administrator login name
X *	%L	Login name (yours)
X *	%M	Number of articles markd with M
X *	%n	Newsgroups from source article
X *	%N	Full name (yours)
X *	%o	Organization (yours)
X *	%O	Original working directory (where you ran rn from)
X *	%p	Your private news directory (-d switch)
X *	%P	Public news spool directory (SPOOLDIR)
X *	%r	Last reference (parent article id)
X *	%R	New references list
X *	%s	Subject, with all Re's and (nf)'s stripped off
X *	%S	Subject, with one Re stripped off
X *	%t	New To: line derived from From: and Reply-To (Internet always)
X *	%T	New To: line derived from Path:
X *	%u	Number of unread articles
X *	%U	Number of unread articles disregarding current article
X *	%x	News library directory, usually /usr/lib/news
X *	%X	Rn library directory, usually %x/rn
X *	%z	Size of current article in bytes.
X *	%~	Home directory
X *	%.	Directory containing . files
X *	%$	current process number
X *	%{name} Environment variable "name".  %{name-default} form allowed.
X *	%[name]	Header line beginning with "Name: ", without "Name: " 
X *	%"prompt"
X *		Print prompt and insert what is typed.
X *	%`command`
X *		Insert output of command.
X *	%(test_text=pattern?if_text:else_text)
X *		Substitute if_text if test_text matches pattern, otherwise
X *		substitute else_text.  Use != for negated match.
X *		% substitutions are done on test_text, if_text, and else_text.
X *		(Note: %() only works if CONDSUB defined.)
X *	%digit	Substitute the text matched by the nth bracket in the last
X *		pattern that had brackets.  %0 matches the last bracket
X *		matched, in case you had alternatives.
X *
X *	Put ^ in the middle to capitalize the first letter: %^C = Net.jokes
X *	Put _ in the middle to capitalize last component: %_c = net/Jokes
X *
X *	~ interpretation in filename expansion happens after % expansion, so
X *	you could put ~%{NEWSLOGNAME-news} and it will expand correctly.
X */
X
X/* *** System Dependent Stuff *** */
X
X/* NOTE: many of these are defined in the config.h file */
X
X/* name of organization */
X#ifndef ORGNAME
X#   define ORGNAME "ACME Widget Company, Widget Falls, Southern North Dakota"
X#endif
X
X#ifndef MBOXCHAR
X#   define MBOXCHAR 'F'	/* how to recognize a mailbox by 1st char */
X#endif
X
X#ifndef ROOTID
X#   define ROOTID 0        /* uid of superuser */
X#endif
X
X#ifdef NORMSIG
X#   define sigset signal
X#   define sigignore(sig) signal(sig,SIG_IGN)
X#endif
X
X#ifndef LOGDIRFIELD
X#   define LOGDIRFIELD 6		/* Which field (origin 1) is the */
X					/* login directory in /etc/passwd? */
X					/* (If it is not kept in passwd, */
X					/* but getpwnam() returns it, */
X					/* define the symbol GETPWENT) */
X#endif
X#ifndef GCOSFIELD
X#   define GCOSFIELD 5
X#endif
X
X#ifndef NEGCHAR
X#   define NEGCHAR '!'
X#endif
X
X/* Space conservation section */
X
X/* To save D space, cut down size of MAXRCLINE, NGMAX, VARYSIZE. */
X#define MAXRCLINE 1500	/* number of lines allowed in .newsrc */
X			/* several parallel arrays affected. */
X			/* (You can have more lines in the active file, */
X			/* just not in the .newsrc) */
X#define HASHSIZ 1693	/* should be prime, and at least MAXRCLINE + 10% */
X#define NGMAX 100	/* number of newsgroups allowed on command line */
X			/* undefine ONLY symbol to disable "only" feature */
X#define VARYSIZE 256	/* this makes a block 1024 bytes long in DECville */
X			/* (used by virtual array routines) */
X
X/* Undefine any of the following features to save both I and D space */
X/* In general, earlier ones are easier to get along without */
X/* Pdp11's without split I and D may have to undefine them all */
X#define DEBUGGING	/* include debugging code */
X#define USETHREADS	/* Add article-thread following */
X#define CUSTOMLINES	/* include code for HIDELINE and PAGESTOP */
X#define PUSHBACK	/* macros and keymaps using pushback buffer */
X#define SPEEDOVERMEM	/* use more memory to run faster */
X#define WORDERASE	/* enable ^W to erase a word */
X#define MAILCALL	/* check periodically for mail */
X#define CLEAREOL	/* use clear to end-of-line instead of clear screen */
X#define NOFIREWORKS	/* keep whole screen from flashing on certain */
X			/* terminals such as older Televideos */
X#define VERIFY		/* echo the command they just typed */
X#define HASHNG		/* hash newsgroup lines for fast lookup-- */
X			/* linear search used if not defined */
X#define CONDSUB		/* allow %(cond?text:text) */
X#define BACKTICK	/* allow %`command` */
X#define PROMPTTTY	/* allow %"prompt" */
X#define ULSMARTS	/* catch _^H in text and do underlining */
X#define TERMMOD		/* allow terminal type modifier on switches */
X#define BAUDMOD		/* allow baudrate modifier on switches */
X#define GETLOGIN	/* use getlogin() routine as backup to environment */
X			/* variables USER or LOGNAME */
X#define ORGFILE		/* if organization begins with /, look up in file */
X#define TILDENAME	/* allow ~logname expansion */
X#define SETENV		/* allow command line environment variable setting */
X#define GETWD		/* use our getwd() instead of piped in pwd */
X#define MAKEDIR		/* use our makedir() instead of shell script */
X#define MEMHELP		/* keep help messages in memory */
X#define VERBOSE		/* compile in more informative messages */
X#define TERSE		/* compile in shorter messages */
X			/* (Note: both VERBOSE and TERSE can be defined; -t
X			 * sets terse mode.  One or the other MUST be defined.
X			 */
X#ifndef pdp11
X#   define CACHESUBJ	/* cache subject lines in memory */
X			/* without this ^N still works but runs really slow */
X			/* but you save lots and lots of D space */
X#   define CACHEFIRST	/* keep absolute first article numbers in memory */
X			/* cost: about 2k */
X#endif
X#define ROTATION	/* enable x, X and ^X commands to work */
X#define DELBOGUS	/* ask if bogus newsgroups should be deleted */
X#define RELOCATE	/* allow newsgroup rearranging */
X#define ESCSUBS		/* escape substitutions in multi-character commands */
X#define DELAYMARK	/* allow articles to be temporarily marked as read */
X			/* until exit from current newsgroup or Y command */
X#define MCHASE		/* unmark xrefed articles on m or M */
X#define MUNGHEADER	/* allow alternate header formatting via */
X			/* environment variable ALTHEADER (not impl) */
X#define ASYNC_PARSE	/* allow parsing headers asyncronously to reading */
X			/* used by MCHASE and MUNGHEADER */
X#define FINDNEWNG	/* check for new newsgroups on startup */
X#define FASTNEW		/* do optimizations on FINDNEWNG for faster startup */
X			/* (this optimization can make occasional mistakes */
X			/* if a group is removed and another group of the */
X			/* same length is added, and if no softpointers are */
X			/* affected by said change.) */
X#define INNERSEARCH	/* search command 'g' with article */
X#define CATCHUP		/* catchup command at newsgroup level */
X#define NGSEARCH	/* newsgroup pattern matching */
X#define ONLY		/* newsgroup restrictions by pattern */
X#define KILLFILES	/* automatic article killer files */
X#define ARTSEARCH	/* pattern searches among articles */
X			/* /, ?, ^N, ^P, k, K */
X
X/* some dependencies among options */
X
X#ifndef ARTSEARCH
X#   undef KILLFILES
X#   undef INNERSEARCH
X#   undef CACHESUBJ
X#endif
X
X#ifndef DELAYMARK
X#   ifndef MCHASE
X#	ifndef MUNGHEADER
X#	    undef ASYNC_PARSE
X#	endif
X#   endif
X#endif
X
X#ifndef SETUIDGID
X#   define eaccess access
X#endif
X
X#ifdef ONLY				/* idiot lint doesn't grok #if */
X#   define NGSORONLY
X#else
X#   ifdef NGSEARCH
X#	define NGSORONLY
X#   endif
X#endif
X
X#ifdef VERBOSE
X#   ifdef TERSE
X#	define IF(c) if (c)
X#	define ELSE else
X#   else
X#	define IF(c)
X#	define ELSE
X#   endif
X#else /* !VERBOSE */
X#   ifndef TERSE
X#	define TERSE
X#   endif
X#   define IF(c) "IF" outside of VERBOSE???
X#   define ELSE "ELSE" outside of VERBOSE???
X#endif
X
X#ifdef DEBUGGING
X#   define assert(ex) {if (!(ex)){fprintf(stderr,"Assertion failed: file %s, line %d\n", __FILE__, __LINE__);sig_catcher(0);}}
X#else
X#   define assert(ex) ;
X#endif
X
X#ifdef SPEEDOVERMEM
X#   define OFFSET(x) (x)
X#else
X#   define OFFSET(x) ((x)-absfirst)
X#endif
X
X/* If you're strapped for space use the help messages in shell scripts */
X/* if {NG,ART,PAGER,SUBS}HELP is undefined, help messages are in memory */
X#ifdef MEMHELP  /* undef MEMHELP above to get them all as sh scripts */
X#   undef NGHELP
X#   undef ARTHELP
X#   undef PAGERHELP
X#   undef SUBSHELP
X#else
X#   ifndef NGHELP			/* % and ~ */
X#	define NGHELP "%X/ng.help"
SHAR_EOF
echo "End of part 5"
echo "File common.h is continued in part 6"
echo "6" > s2_seq_.tmp
exit 0

exit 0 # Just in case...
-- 
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.



More information about the Comp.sources.unix mailing list