[net.sources] rn version 4.1, part 6 of 8

lwall@sdcrdcf.UUCP (Larry Wall) (10/13/84)

#! /bin/sh

# Make a new directory for the rn sources, cd to it, and run kits 1 thru 8 
# through sh.  When all 8 kits have been run, read README.

echo "This is rn kit 6 (of 8).  If kit 6 is complete, the line"
echo '"'"End of kit 6 (of 8)"'" will echo at the end.'
echo ""
export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
echo Extracting help.c
cat >help.c <<'!STUFFY!FUNK!'
/* $Header: help.c,v 4.1 84/09/24 11:48:20 lwall Exp $
 *
 * $Log:	help.c,v $
 * Revision 4.1  84/09/24  11:48:20  lwall
 * Real baseline.
 * 
 * Revision 4.0.1.1  84/09/10  15:11:41  lwall
 * Delinted.
 * 
 * Revision 4.0  84/09/04  09:50:27  lwall
 * Baseline for netwide release
 * 
 */

#include "EXTERN.h"
#include "common.h"
#include "rn.h"
#include "term.h"
#include "INTERN.h"
#include "help.h"

void
help_init()
{
    ;
}

void
help_page()
{
#ifdef PAGERHELP
    doshell(sh,filexp(PAGERHELP));
#else
    putchar('\n');
    page_line = 1;
    print_lines("\
Paging commands:\n\
",STANDOUT);
    print_lines("\n\
SP	Display the next page.\n\
x	Display the next page decrypted (rot13).\n\
d	Display half a page more.\n\
CR	Display one more line.\n\
^R,v,^X	Restart the current article (v=verbose header, ^X=rot13).\n\
",NOMARKING);
    print_lines("\
^B	Back up one page.\n\
^L,X	Refresh the screen (X=rot13).\n\
g pat	Go to (search forward within article for) pattern.\n\
G	Search again for current pattern within article.\n\
^G	Search for next line beginning with \"Subject:\".\n\
q	Quit the pager, go to end of article.  Leave article read or unread.\n\
j	Junk this article (mark it read).  Goes to end of article.\n\
\n\
",NOMARKING);
    print_lines("\
The following commands skip the rest of the current article, then behave\n\
just as if typed to the 'What next?' prompt at the end of the article:\n\
",STANDOUT);
    print_lines("\n\
n	Scan forward for next unread article.\n\
N	Go to next article.\n\
^N	Scan forward for next unread article with same title.\n\
p,P,^P	Same as n,N,^N, only going backwards.\n\
-	Go to previously displayed article.\n\
\n\
",NOMARKING);
    print_lines("\
The following commands also take you to the end of the article.\n\
Type h at end of article for a description of these commands:\n\
",STANDOUT);
    print_lines("\
	# $ & / = ? c C f F k K ^K m M number r R ^R s S u v w W Y ^ |\n\
\n\
(To return to the middle of the article after one of these commands, type ^L.)\n\
",NOMARKING);
#endif
}

void
help_art()
{
#ifdef ARTHELP
    doshell(sh,filexp(ARTHELP));
#else
    putchar('\n');
    page_line = 1;
    print_lines("\
Article Selection commands:\n\
",STANDOUT);
    print_lines("\n\
n,SP	Scan forward for next unread article.\n\
N	Go to next article.\n\
^N	Scan forward for next unread article with same subject.\n\
p,P,^P	Same as n,N,^N, only going backwards.\n\
-	Go to previously displayed article.\n\
",NOMARKING);
    print_lines("\
number	Go to specified article.\n\
range{,range} command{:command}\n\
	Apply one or more commands to one or more ranges of articles.\n\
	Ranges are of the form: number | number-number.  You may use . for\n\
	the current article, and $ for the last article.\n\
 	Valid commands are: j, m, M, s, S, and !.\n\
",NOMARKING);
    print_lines("\
/pattern/modifiers\n\
	Scan forward for article containing pattern in the subject line.\n\
	(Use ?pat? to scan backwards; append h to scan headers, a to scan\n\
	entire articles, r to scan read articles, c to make case sensitive.\n\
/pattern/modifiers:command{:command}\n\
	Apply one or more commands to the set of articles matching pattern.\n\
	Use a K modifier to save entire command to the KILL file for this\n\
	newsgroup.  Commands m and M, if first, imply an r modifier.\n\
 	Valid commands are: j, m, M, s, S, and !.\n\
",NOMARKING);
    print_lines("\
f,F	Submit a followup article (F = include this article).\n\
r,R	Reply through net mail (R = include this article).\n\
s ...	Save to file or pipe via sh.\n\
S ...	Save via preferred shell.\n\
w,W	Like s and S but save without the header.\n\
| ...	Same as s|...\n\
C	Cancel this article, if yours.\n\
",NOMARKING);
    print_lines("\
^R,v	Restart article (v=verbose).\n\
^X	Restart article, rot13 mode.\n\
c	Catch up (mark all articles as read).\n\
^B	Back up one page.\n\
^L	Refresh the screen.  You can get back to the pager with this.\n\
X	Refresh screen in rot13 mode.\n\
",NOMARKING);
    print_lines("\
^	Go to first unread article.  Disables subject search mode.\n\
$	Go to end of newsgroup.  Disables subject search mode.\n\
",NOMARKING);
    print_lines("\#       Print last article number.\n\
&	Print current values of command-line switches.\n\
&switch {switch}\n\
	Set or unset more switches.\n\
j	Junk this article (mark it read).  Stays at end of article.\n\
m	Mark article as still unread.\n\
M	Mark article as still unread upon exiting newsgroup or Y command.\n\
",NOMARKING);
    print_lines("\
Y	Yank back articles marked temporarily read via M.\n\
k	Mark current SUBJECT as read.\n\
K	Mark current SUBJECT as read, and save command in KILL file.\n\
=	List subjects of unread articles.\n\
u	Unsubscribe to this newsgroup.\n\
^K	Edit local KILL file (the one for this newsgroup).\n\
q	Quit this newsgroup for now.\n\
",NOMARKING);
#endif
}

void
help_ng()
{
#ifdef NGHELP
    doshell(sh,filexp(NGHELP));
#else
    putchar('\n');
    page_line = 1;
    print_lines("\
Newsgroup Selection commands:\n\
",STANDOUT);
    if (ng != nextrcline)
	print_lines("\
\n\
y,SP	Do this newsgroup now.\n\
.cmd	Do this newsgroup, executing cmd as first command.\n\
=	Equivalent to .=<carriage return>.\n\
u	Unsubscribe from this newsgroup.\n\
c	Catch up (mark this newsgroup all read).\n\
",NOMARKING);
    print_lines("\
\n\
n	Go to the next newsgroup with unread news.\n\
N	Go to the next newsgroup.\n\
p	Go to the previous newsgroup with unread news.\n\
P	Go to the previous newsgroup.\n\
",NOMARKING);
    print_lines("\
-	Go to the previously displayed newsgroup.\n\
1	Go to the first newsgroup.\n\
^	Go to the first newsgroup with unread news.\n\
$	Go to the last newsgroup.\n\
",NOMARKING);
    print_lines("\
g name	Go to the named newsgroup.  Subscribe to new newsgroups this way too.\n\
/pat	Search forward for newsgroup matching pattern.\n\
?pat	Search backward for newsgroup matching pattern.\n\
	(Use * and ? style patterns.  Append r to include read newsgroups.)\n\
",NOMARKING);
    print_lines("\
l pat	List unsubscribed newsgroups containing pattern.\n\
m name	Move named newsgroup elsewhere (no name moves current newsgroup).\n\
o pat	Only display newsgroups matching pattern.  Omit pat to unrestrict.\n\
a pat	Like o, but also scans for unsubscribed newsgroups matching pattern.\n\
L	List current .newsrc.\n\
",NOMARKING);
    print_lines("\
&	Print current command-line switch settings.\n\
&switch {switch}\n\
	Set (or unset) more command-line switches.\n\
!cmd	Shell escape.\n\
",NOMARKING);
    print_lines("\
q	Quit rn.\n\
^K	Edit the global KILL file.  Use commands like /pattern/j to suppress\n\
	pattern in every newsgroup.\n\
v	Print version.\n\
",NOMARKING);
#endif
}

#ifdef ESCSUBS
void
help_subs()
{
#ifdef SUBSHELP
    doshell(sh,filexp(SUBSHELP));
#else
    putchar('\n');
    page_line = 1;
    print_lines("\
Valid substitutions are:\n\
",STANDOUT);
    print_lines("\
\n\
a	Current article number\n\
A	Full name of current article (%P/%c/%a)\n\
b	Destination of last save command, often a mailbox\n\
B	Bytes to ignore at beginning of last saved article\n\
",NOMARKING);
    print_lines("\
c	Current newsgroup, directory form\n\
C	Current newsgroup, dot form\n\
d	Full name of newsgroup directory (%P/%c)\n\
D	Distribution line from current article\
",NOMARKING);
    print_lines("\
f	Who the current article is from\n\
F	Newsgroups to followup to (from Newsgroups and Followup-To)\n\
h	(This help message)\n\
H	Host name (yours)\n\
i	Message-I.D. line from current article, with <>\n\
",NOMARKING);
    print_lines("\
l	News administrator's login name, if any\n\
L	Login name (yours)\n\
M	Number of article marked with M\n\
n	Newsgroups from current article\n\
N	Full name (yours)\n\
",NOMARKING);
    print_lines("\
o	Organization (yours)\n\
O	Original working directory (where you ran rn from)\n\
p	Your private news directory (from -d)\n\
P	Public news spool directory\n\
",NOMARKING);
    print_lines("\
r	Last reference (parent article id)\n\
R	References list for followup article\n\
s	Subject, with all Re's and (nf)'s stripped off\n\
S	Subject, with one Re stripped off\
",NOMARKING);
    print_lines("\
t	New To line derived from From and Reply-To (Internet format)\n\
T	New To line derived from Path\n\
u	Number of unread articles\n\
U	Number of unread articles not counting current article\n\
x	News library directory\n\
X	Rn library directory\n\
",NOMARKING);
    print_lines("\
~	Your home directory\n\
.	Directory containing . files\n\
$	Current process number\n\
/	Last search string\n\
ESC	Run preceding command through % interpretation\n\
",NOMARKING);
#endif
}
#endif

!STUFFY!FUNK!
echo Extracting artsrch.c
cat >artsrch.c <<'!STUFFY!FUNK!'
/* $Header: artsrch.c,v 4.1 84/09/24 11:42:18 lwall Exp $
 *
 * $Log:	artsrch.c,v $
 * Revision 4.1  84/09/24  11:42:18  lwall
 * Real baseline.
 * 
 * Revision 4.0.1.1  84/09/10  15:05:28  lwall
 * Delinted.
 * 
 * Revision 4.0  84/09/04  09:49:35  lwall
 * Baseline for netwide release
 * 
 */

#include "EXTERN.h"
#include "common.h"
#include "search.h"
#include "term.h"
#include "util.h"
#include "intrp.h"
#include "bits.h"
#include "kfile.h"
#include "head.h"
#include "final.h"
#include "cheat.h"
#include "ng.h"
#include "artio.h"
#include "INTERN.h"
#include "artsrch.h"

void
artsrch_init()
{
#ifdef ARTSEARCH
#ifdef ZEROGLOB
    init_compex(&sub_compex);
    init_compex(&art_compex);
#endif
#endif
}

/* search for an article containing some pattern */

#ifdef ARTSEARCH
int
art_search(patbuf,get_cmd)
char *patbuf;				/* if patbuf != buf, get_cmd must */
int get_cmd;				/*   be set to FALSE!!! */
{
    char *pattern;			/* unparsed pattern */
    register char cmdchr = *patbuf;	/* what kind of search? */
    register char *s;
    bool backward = cmdchr == '?' || cmdchr == Ctl('p');
					/* direction of search */
    COMPEX *compex;			/* which compiled expression */
    char *cmdlst = Nullch;		/* list of commands to do */
    int normal_return = SRCH_NOTFOUND;	/* assume no commands */
    bool saltaway = FALSE;		/* store in KILL file? */
    char howmuch;			/* search just the subjects */
    bool doread;			/* search read articles? */
    bool foldcase = TRUE;		/* fold upper and lower case? */

    int_count = 0;
    if (cmdchr == '/' || cmdchr == '?') {	/* normal search? */
	if (get_cmd && buf == patbuf)
	    if (!finish_command(FALSE))	/* get rest of command */
		return SRCH_ABORT;
	compex = &art_compex;
	if (patbuf[1]) {
	    howmuch = 0;
	    doread = FALSE;
	}
	else {
	    howmuch = art_howmuch;
	    doread = art_doread;
	}
	s = cpytill(buf,patbuf+1,cmdchr);/* ok to cpy buf+1 to buf */
	pattern = buf;
	if (*pattern) {
	    if (*lastpat)
		free(lastpat);
	    lastpat = savestr(pattern);
	}
	if (*s) {			/* modifiers or commands? */
	    for (s++; *s && index("Kharc",*s); s++) {
		if (*s == 'h')		/* scan header */
		    howmuch = 1;
		else if (*s == 'a')	/* scan article */
		    howmuch = 2;
		else if (*s == 'r')	/* scan read articles */
		    doread = TRUE;
		else if (*s == 'K')	/* put into KILL file */
		    saltaway = TRUE;
		else if (*s == 'c')	/* make search case sensitive */
		    foldcase = FALSE;
	    }
	}
	while (isspace(*s) || *s == ':')
	    s++;
	if (*s) {
	    if (*s == 'm' || *s == 'M')
		doread = TRUE;
	    if (*s == 'k')		/* grandfather clause */
		*s = 'j';
	    cmdlst = savestr(s);
	    normal_return = SRCH_DONE;
	}
	art_howmuch = howmuch;
	art_doread = doread;
	if (srchahead)
	    srchahead = -1;
    }
    else {
	register char *h;

	howmuch = 0;			/* just search subjects */
	doread = (cmdchr == Ctl('p'));
	if (cmdchr == Ctl('n'))
	    normal_return = SRCH_SUBJDONE;
	compex = &sub_compex;
	pattern = patbuf+1;
	strcpy(pattern,": *");
	h = pattern + strlen(pattern);
	interp(h,"%s");		/* fetch current subject */
	if (cmdchr == 'K') {
	    saltaway = TRUE;
	    cmdchr = 'k';
	}
	if (cmdchr == 'k') {
	    normal_return = SRCH_DONE;
	    cmdlst = savestr("j");
	    mark_as_read(art);		/* this article has this subject */
	    if (!*h) {
#ifdef VERBOSE
		IF(verbose)
		    fputs("\nCannot delete null subject.\n",stdout);
		ELSE
#endif
#ifdef TERSE
		    fputs("\nNull subject.\n",stdout);
#endif
		return SRCH_ABORT;
	    }
#ifdef VERBOSE
	    else if (verbose)
		printf("\nMarking subject \"%s\" as read.\n",h);
#endif
	}
	else if (!srchahead)
	    srchahead = -1;
	h[24] = '\0';		/* compensate for notesfiles */
	while (*h) {
	    if (index("\\[.^*$'\"",*h) != Nullch)
		*h++ = '.';
	    else
		h++;
	}
#ifdef DEBUGGING
	if (debug) {
	    printf("\npattern = %s\n",pattern);
	}
#endif
    }
    if ((s = compile(compex,pattern,TRUE,foldcase)) != Nullch) {
					/* compile regular expression */
	printf("\n%s\n",s);
	return SRCH_ABORT;
    }
#ifdef KILLFILES
    if (saltaway) {
	char saltbuf[LBUFLEN];

	s = saltbuf;
	sprintf(s,"/%s/",pattern);
	s += strlen(s);
	if (doread)
	    *s++ = 'r';
	if (howmuch==1)
	    *s++ = 'h';
	else if (howmuch==2)
	    *s++ = 'a';
	*s++ = ':';
	if (!cmdlst)
	    cmdlst = savestr("j");
	safecpy(s,cmdlst,LBUFLEN-(s-saltbuf));
	kf_append(saltbuf);
    }
#endif
    if (cmdlst && index(cmdlst,'='))
	normal_return = SRCH_ERROR;	/* listing subjects is an error? */
    if (get_cmd) {
	fputs("\nSearching...\n",stdout);
					/* give them something to read */
    }
    if (!backward && art > lastart)
	art = (doread ? absfirst : firstart) - 1;
    if (srchahead > 0) {
	if (!backward)
	    art = srchahead - 1;
	srchahead = -1;
    }
    assert(!cmdlst || *cmdlst);
    for (;;) {
	if (int_count) {
	    int_count = 0;
	    if (cmdlst)
		free(cmdlst);
	    return SRCH_INTR;
	}
	if (backward ?
		(--art < absfirst || (!doread && art < firstart)) :
		(++art > lastart)
	  ) {			/* out of articles? */
	    if (cmdlst)
		free(cmdlst);
	    return normal_return;
	}
	/*NOSTRICT*/
	if (doread || !was_read(art)) {
	    if (wanted(compex,art,howmuch)) {
				    /* does the shoe fit? */
		if (cmdlst) {
		    if (perform(cmdlst,TRUE)) {
			if (cmdlst)
			    free(cmdlst);
			return SRCH_INTR;
		    }
		}
		else {
		    if (cmdlst)
			free(cmdlst);
		    return SRCH_FOUND;
		}
	    }
	    else if (!cmdlst && ! (art%50)) {
		printf("...%ld",(long)art);
		fflush(stdout);
	    }
	}
    }
}

/* determine if article fits pattern */
/* returns TRUE if it exists and fits pattern, FALSE otherwise */

bool
wanted(compex, artnum, scope)
COMPEX *compex;
ART_NUM artnum;
char scope;
{
    if (!scope) {
	char subj_buf[266];
	
	strcpy(subj_buf, "Subject: ");
	strncpy(subj_buf+9,fetchsubj(artnum,FALSE,FALSE),256);
#ifdef DEBUGGING
	if (debug & DEB_SEARCH_AHEAD)
	    printf("%s\n",subj_buf);
#endif
	return execute(compex,subj_buf) != Nullch;
    }
#ifdef CACHESUBJ
    else
	fetchsubj(artnum,FALSE,FALSE);/* might as well get subject handy */
#endif
    
    if (artopen(artnum) == Nullfp)	/* ensure that article is open */
	return FALSE;			/* if not, return NO MATCH */
    scope--;
    while (fgets(buf,LBUFLEN,artfp) != Nullch) {
					/* for each line of article */
	if (!scope && index(buf,':') == Nullch && *buf != ' ' && *buf != '\t')
					/* if headers only and out of header */
	    return FALSE;		/* say no go */
	if (execute(compex,buf) != Nullch) {
					/* does pattern matcher match? */
	    return TRUE;		/* say Eureka */
	}
    }
    return FALSE;			/* out of article, so no match */
}
#endif

!STUFFY!FUNK!
echo Extracting init.c
cat >init.c <<'!STUFFY!FUNK!'
/* $Header: init.c,v 4.1 84/09/24 11:56:37 lwall Exp $
 *
 * $Log:	init.c,v $
 * Revision 4.1  84/09/24  11:56:37  lwall
 * Real baseline.
 * 
 * Revision 4.0.1.2  84/09/12  17:36:04  lwall
 * pwd.h now included by common.h.
 * 
 * Revision 4.0.1.1  84/09/10  15:12:37  lwall
 * Delinted.
 * 
 * Revision 4.0  84/09/04  09:50:42  lwall
 * Baseline for netwide release
 * 
 */

#include "EXTERN.h"
#include "common.h"
#include "util.h"
#include "final.h"
#include "term.h"
#include "last.h"
#include "rn.h"
#include "rcstuff.h"
#include "ngdata.h"
#include "util.h"
#include "only.h"
#include "intrp.h"
#include "addng.h"
#include "sw.h"
#include "art.h"
#include "artsrch.h"
#include "artio.h"
#include "backpage.h"
#include "bits.h"
#include "cheat.h"
#include "head.h"
#include "help.h"
#include "kfile.h"
#include "ngsrch.h"
#include "ngstuff.h"
#include "rcln.h"
#include "respond.h"
#include "ng.h"
#include "INTERN.h"
#include "init.h"

bool
initialize(argc,argv)
int argc;
char *argv[];
{
    char *tcbuf;
    register bool foundany = FALSE;
    long time();

    tcbuf = safemalloc(1024);		/* make temp buffer for termcap and */
					/* other initialization stuff */
    
    /* decode switches */

    sw_init(argc,argv,tcbuf);               /* must not do % interps! */
					/* (but may mung environment) */

    /* start up file expansion and the % interpreter */

    intrp_init(tcbuf);
    
    /* now make sure we have a current working directory */

    cwd_check();
    
    /* now that we know where to save things, cd to news directory */

    if (chdir(spool)) {
	printf(nocd,spool);
	finalize(1);
    }

    /* init signals, status flags and terminal stuff */

    final_init();
    term_init(tcbuf);
    
    /* get info on last rn run, if any */

    last_init(tcbuf);

    free(tcbuf);			/* recover 1024 bytes */

    /* make sure we are the right version */

    version_check();

    /* make sure we are the sole possessors of .newsrc */

    lock_check();

    /* check for news news */

    newsnews_check();

    /* open active file, etc. */

    ngdata_init();

    /* now read in the .newsrc file */

    foundany = rcstuff_init();

    /* it looks like we will actually read something, so init everything */

    addng_init();
    art_init();
    artio_init();
    artsrch_init();
    backpage_init();
    bits_init();
    cheat_init();
/*  final_init();	already done */
    head_init();
    help_init();
/*  intrp_init();      already done */
    kfile_init();
/*  last_init();	already done */
    ng_init();
/*  ngdata_init();	already done */
    ngsrch_init();
    ngstuff_init();
    only_init();
    rcln_init();
/*  rcstuff_init();	already done */
    respond_init();
    rn_init();
    search_init();
/*  sw_init();      already done */
/*  term_init();	already done */
    util_init();

#ifdef FINDNEWNG
    fstat(actfp->_file,&filestat);	/* did active file grow? */
    if (filestat.st_size != lastactsiz) {
	long actsiz = filestat.st_size;	/* remember new size */
	NG_NUM oldnext = nextrcline;	/* remember # lines in newsrc */
#ifdef FASTNEW
	bool munged = writesoft || !lastactsiz;
					/* bad soft ptrs -> edited active */
#else
	bool munged = TRUE;		/* just assume .newsrc munged */
#endif

#ifdef VERBOSE
	IF(verbose)
	    fputs("\nChecking active list for new newsgroups...\n",stdout);
	ELSE
#endif
#ifdef TERSE
	    fputs("\nNew newsgroups:\n",stdout);
#endif
#ifdef FASTNEW
	if (!munged) {			/* maybe just do tail of file? */
	    fseek(actfp,lastactsiz-1,0);
	    fgets(buf,LBUFLEN,actfp);
	    munged = (*buf != '\n');
	    if (!munged)
		munged = newlist(munged,FALSE);
	}
#endif
	if (munged) {			/* must we scan entire file? */
	    fseek(actfp,0L,0);		/* rewind active file */
	    newlist(munged,FALSE);      /* sure hope they use hashing... */
	}
	lastactsiz = actsiz;		/* remember for .rnlast */
	if (nextrcline != oldnext) {	/* did we add any new groups? */
	    foundany = TRUE;		/* let main() know */
	    starthere = 0;              /* and start ng scan from the top */
	}
    }
#endif
    time(&lasttime);			/* remember when we inited-- */
					/* ends up back in .rnlast */
    writelast();                       /* in fact, put it there now */
    
#ifdef FINDNEWNG
# ifdef ONLY
    if (maxngtodo)			/* patterns on command line? */
	foundany |= scanactive();
# endif
#endif

    return foundany;
}

/* make sure there is no rn out there already */

void
lock_check()
{
    lockname = savestr(filexp(LOCKNAME));
    if (!checkflag) {
	tmpfp = fopen(lockname,"r");
	if (tmpfp != Nullfp) {
	    int processnum;

	    fgets(buf,LBUFLEN,tmpfp);
	    fclose(tmpfp);
	    processnum = atoi(buf);
#ifdef VERBOSE
	    IF(verbose)
		printf("You seem to have left an rn running, process %d.\n",
		    processnum);
	    ELSE
#endif
#ifdef TERSE
		printf("Rn left running, #%d.\n", processnum);
#endif
	    if (kill(processnum, SIGEMT)) {
				    /* does process not exist? */
				    /* (rn ignores SIGEMT) */
		sleep(2);
#ifdef VERBOSE
		IF(verbose)
		    fputs("\n\
That process does not seem to exist anymore.  The count of read articles\n\
may be incorrect in the last newsgroup accessed by that other (defunct)\n\
process.\n\n",stdout);
		ELSE
#endif
#ifdef TERSE
		    fputs("\nProcess crashed.\n",stdout);
#endif
		if (*lastngname) {
#ifdef VERBOSE
		    IF(verbose)
			printf("(The last newsgroup accessed was %s.)\n\n",
			lastngname);
		    ELSE
#endif
#ifdef TERSE
			printf("(In %s.)\n\n",lastngname);
#endif
		}
		get_anything();
		putchar('\n');
	    }
	    else {
#ifdef VERBOSE
		IF(verbose)
		    fputs("\n\
You may not have two copies of rn running simultaneously.  Goodbye.\n\
",stdout);
		ELSE
#endif
#ifdef TERSE
		    fputs("\nCan't start another.\n",stdout);
#endif
		finalize(0);
	    }
	}
	tmpfp = fopen(lockname,"w");
	fprintf(tmpfp,"%d\n",getpid());
	fclose(tmpfp);
    }
}

void
newsnews_check()
{
    char *newsnewsname = filexp(NEWSNEWSNAME);

    if (!checkflag && (tmpfp = fopen(newsnewsname,"r")) != Nullfp) {
	fstat(tmpfp->_file,&filestat);
	if (filestat.st_mtime > lasttime) {
	    while (fgets(buf,sizeof(buf),tmpfp) != Nullch)
		fputs(buf,stdout);
	    get_anything();
	    putchar('\n');
	}
	fclose(tmpfp);
    }
}

void
version_check()
{
    set_ngname("net.announce");
    if (access(ngdir,0)) {
#ifdef VERBOSE
	IF(verbose)
	    fputs("Can't find net.announce.  Wrong news version?\n",stdout);
	ELSE
#endif
#ifdef TERSE
	    fputs("Wrong version?\n",stdout);
#endif
	finalize(1);
    }
}
!STUFFY!FUNK!
echo Extracting head.c
cat >head.c <<'!STUFFY!FUNK!'
/* $Header: head.c,v 4.1 84/09/24 11:47:10 lwall Exp $
 *
 * $Log:	head.c,v $
 * Revision 4.1  84/09/24  11:47:10  lwall
 * Real baseline.
 * 
 * Revision 4.0.1.1  84/09/10  15:11:08  lwall
 * Delinted.
 * 
 * Revision 4.0  84/09/04  09:50:17  lwall
 * Baseline for netwide release
 * 
 */

#include "EXTERN.h"
#include "common.h"
#include "artio.h"
#include "bits.h"
#include "util.h"
#include "INTERN.h"
#include "head.h"

bool first_one;		/* is this the 1st occurance of this header line? */

static char htypeix[26] =
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

void
head_init()
{
    register int i;

    for (i=HEAD_FIRST+1; i<HEAD_LAST; i++)
	htypeix[*htype[i].ht_name - 'a'] = i;
}

int
set_line_type(bufptr,colon)
char *bufptr;
register char *colon;
{
    char lc[LONGKEY+3];
    register char *t, *f;
    register int i, len;

    for (t=lc,f=bufptr; f<colon; f++, t++) {
	if (isspace(*f))
	/* guard against space before : */
	    break;
	*t = isupper(*f) ? tolower(*f) : *f;
    }
    *t = '\0';
    f = lc;				/* get lc into register */
    len = t - f;

    /* now scan the headtype table, backwards so we don't have to supply an
     * extra terminating value, using first letter as index, and length as
     * optimization to avoid calling subroutine strEQ unnecessarily.  Hauls.
     */
    
    if (islower(*f)) {
	for (i = htypeix[*f - 'a']; *htype[i].ht_name == *f; --i) {
	    if (len == htype[i].ht_length && strEQ(f, htype[i].ht_name)) {
		return i;
	    }
	}
    }
    return SOME_LINE;
}

void
start_header(artnum)
ART_NUM artnum;
{
    register int i;

    for (i=0; i<HEAD_LAST; i++) {
	htype[i].ht_minpos = -1;
	htype[i].ht_maxpos = 0;
    }
    in_header = SOME_LINE;
    first_one = FALSE;
#ifdef ASYNC_PARSE
    parsed_art = artnum;
#endif
}

bool
parseline(art_buf,newhide,oldhide)
char *art_buf;
int newhide, oldhide;
{
    if (*art_buf == ' ' || *art_buf == '\t')
					/* header continuation line? */
	return oldhide;
    else {				/* maybe another header line */
	char *s;

	if (first_one) {		/* did we just pass 1st occurance? */
	    first_one = FALSE;
	    htype[in_header].ht_maxpos = artpos;
					/* remember where line left off */
	}
	s = index(art_buf,':');
	if (s == Nullch || s-art_buf > LONGKEY+2) {
			    /* is it the end of the header? */
	    htype[PAST_HEADER].ht_minpos =
		(*art_buf == '\n') ? ftell(artfp) : artpos;
			    /* remember where body starts */
	    in_header = PAST_HEADER;
	}
	else {	/* it is a new header line */
	    in_header = set_line_type(art_buf,s);
	    first_one = (htype[in_header].ht_minpos < 0);
	    if (htype[in_header].ht_minpos < 0)
		htype[in_header].ht_minpos = artpos;
	    if (htype[in_header].ht_flags & HT_HIDE)
		return newhide;
	}
    }
    return FALSE;			/* don't hide this line */
}

#ifdef ASYNC_PARSE
int
parse_maybe(artnum)
ART_NUM artnum;
{
    char tmpbuf[LBUFLEN];

    if (parsed_art == artnum)
	return 0;
    /* no maybe about it now */
    if (artopen(artnum) == Nullfp) {
	return -1;
    }
    start_header(artnum);
    while (in_header) {
	artpos = ftell(artfp);
	if (fgets(tmpbuf,LBUFLEN,artfp) == Nullch)
	    break;
	parseline(tmpbuf,FALSE,FALSE);
    }
    in_header = PAST_HEADER;
    return 0;
}
#endif

/* get the subject line for an article */

char *
fetchsubj(artnum,current_subject,copy)
ART_NUM artnum;				/* article to get subject from */
bool current_subject;			/* is it in a parsed header? */
bool copy;				/* do you want it savestr()ed? */
{
    char *s = Nullch, *t;

#ifdef CACHESUBJ
    if (!subj_list) {
	register ART_NUM i;
	
	/*NOSTRICT*/
	subj_list =
	    (char**)safemalloc((MEM_SIZE)((OFFSET(lastart)+2)*sizeof(char *)));
	for (i=0; i<=OFFSET(lastart); i++)
	    subj_list[i] = Nullch;
    }
    if (!artnum || artnum > lastart)
	s = nullstr;
    else
	s = subj_list[OFFSET(artnum)];
#endif
    if (s == Nullch) {
	if (current_subject) {
	    s = fetchlines(artnum,SUBJ_LINE);
#ifdef CACHESUBJ
	    subj_list[OFFSET(artnum)] = s;
#endif
	}
	else {
	    s = safemalloc((MEM_SIZE)256);
	    *s = '\0';
	    if (artopen(artnum) != Nullfp) {
		do {
		    if (fgets(s,256,artfp) == Nullch)
			strcpy(s, "Title: \n");
		} while (strnNE(s,"Title:",6) && strnNE(s,"Subject:",8));
		s[strlen(s)-1] = '\0';
		t = index(s,':')+1;
		while (*t == ' ') t++;
		strcpy(s, t);
	    }
	    s = saferealloc(s, (MEM_SIZE)strlen(s)+1);
#ifdef CACHESUBJ
	    subj_list[OFFSET(artnum)] = s;
#endif 
	}
    }
#ifdef CACHESUBJ
    if (copy) {
	t = savestr(s);
	return t;
    }
    else
	return s;
#else
    if (copy)
	return s;
    else {
	safecpy(cmd_buf,s,CBUFLEN);	/* hope this is okay--we're */
	return cmd_buf;			/* really scraping for space here */
    }
#endif
}

/* get header lines from an article */

char *
fetchlines(artnum,which_line)
ART_NUM artnum;				/* article to get line from */
int which_line;				/* type of line desired */
{
    char *newbuf, *t, tmp_buf[LBUFLEN];
    register ART_POS curpos;
    int size;
    register ART_POS firstpos;
    register ART_POS lastpos;
    
#ifdef ASYNC_PARSE
    if (parse_maybe(artnum))
	artnum = 0;
#endif
    firstpos = htype[which_line].ht_minpos;
    lastpos = htype[which_line].ht_maxpos;
    if (!artnum || firstpos < 0 || artopen(artnum) == Nullfp) {
	newbuf = safemalloc((unsigned int)1);
	*newbuf = '\0';
	return newbuf;
    }
    /*NOSTRICT*/
    size = lastpos - firstpos + 1;
#ifdef DEBUGGING
    if (debug && (size < 1 || size > 1000)) {
	printf("Firstpos = %ld, lastpos = %ld\n",(long)firstpos,(long)lastpos);
	gets(tmp_buf);
    }
#endif
    newbuf = safemalloc((unsigned int)size);
    *newbuf = '\0';
    fseek(artfp,firstpos,0);
    for (curpos = firstpos; curpos < lastpos; curpos = ftell(artfp)) {
	if (fgets(tmp_buf,LBUFLEN,artfp) == Nullch)
	    break;
	if (*tmp_buf == ' ' || *tmp_buf == '\t')
	    t = tmp_buf;
	else
	    t = index(tmp_buf,':')+1;
	if (t == Nullch)
	    break;
	else {
	    while (*t == ' ' || *t == '\t') t++;
	    safecat(newbuf,t,size);
	}
    }
    return newbuf;
}

!STUFFY!FUNK!
echo Extracting ngstuff.c
cat >ngstuff.c <<'!STUFFY!FUNK!'
/* $Header: ngstuff.c,v 4.1 84/09/24 12:03:20 lwall Exp $
 *
 * $Log:	ngstuff.c,v $
 * Revision 4.1  84/09/24  12:03:20  lwall
 * Real baseline.
 * 
 * Revision 4.0.1.3  84/09/22  17:03:54  lwall
 * escapade() was not chdiring back.
 * 
 * Revision 4.0.1.2  84/09/19  17:12:10  lwall
 * Ifdef'ed some stuff that should have been.
 * 
 * Revision 4.0.1.1  84/09/10  15:21:21  lwall
 * Delinted.
 * 
 * Revision 4.0  84/09/04  09:51:51  lwall
 * Baseline for netwide release
 * 
 */

#include "EXTERN.h"
#include "common.h"
#include "term.h"
#include "util.h"
#include "ng.h"
#include "bits.h"
#include "intrp.h"
#include "cheat.h"
#include "head.h"
#include "final.h"
#include "sw.h"
#include "INTERN.h"
#include "ngstuff.h"

void
ngstuff_init()
{
    ;
}

/* do a shell escape */

int
escapade()
{
    register char *s;
    bool interactive = (buf[1] == FINISHCMD);
    bool docd;
    char whereiam[256];

    if (!finish_command(interactive))	/* get remainder of command */
	return -1;
    s = buf+1;
    docd = *s != '!';
    if (!docd) {
	s++;
    }
    else {
	getwd(whereiam);
	if (chdir(cwd)) {
	    printf(nocd,cwd);
	    sig_catcher(0);
	}
    }
    while (*s == ' ') s++;
					/* skip leading spaces */
    interp(cmd_buf,s);			/* interpret any % escapes */
    resetty();				/* make sure tty is friendly */
    doshell(Nullch,cmd_buf);	/* invoke the shell */
    noecho();				/* and make terminal */
    crmode();				/*   unfriendly again */
    if (docd) {
	if (chdir(whereiam)) {
	    printf(nocd,whereiam);
	    sig_catcher(0);
	}
    }
#ifdef MAILCALL;
    mailcount = 0;			/* force recheck */
#endif
    return 0;
}

/* process & command */

int
switcheroo()
{
    if (!finish_command(TRUE)) /* get rest of command */
	return -1;	/* if rubbed out, try something else */
    if (!buf[1])
	pr_switches();
    else {
	bool docd = (instr(buf,"-d") != Nullch);
 	char whereami[256];
 
	if (docd)
	    getwd(whereami);
	sw_list(buf+1);
	if (docd) {
	    cwd_check();
	    if (chdir(whereami)) {		/* -d does chdirs */
		printf(nocd,whereami);
		sig_catcher(0);
	    }
	}
    }
    return 0;
}

/* process range commands */

int
numnum()
{
    ART_NUM min, max;
    char *cmdlst = Nullch;
    register char *s, *c;
    ART_NUM oldart = art;
    char tmpbuf[LBUFLEN];
    bool justone = TRUE;		/* assume only one article */

    if (!finish_command(TRUE))	/* get rest of command */
	return NN_INP;
#ifdef ARTSRCH
    if (srchahead)
	srchahead = -1;
#endif
    for (s=buf; *s && (isdigit(*s) || index(" ,-.$",*s)); s++)
	if (!isdigit(*s))
	    justone = FALSE;
    if (*s) {
	cmdlst = savestr(s);
	justone = FALSE;
    }
    else if (!justone)
	cmdlst = savestr("m");
    *s++ = ',';
    *s = '\0';
    safecpy(tmpbuf,buf,LBUFLEN);
    for (s = tmpbuf; c = index(s,','); s = ++c) {
	*c = '\0';
	if (*s == '.')
	    min = oldart;
	else
	    min = atol(s);
	if (min<absfirst) {		/* make sure it is reasonable */
	    min = absfirst;
	    printf("(First article is %ld)\n",(long)absfirst);
	    pad(just_a_sec/3);
	}
	if ((s=index(s,'-')) != Nullch) {
	    s++;
	    if (*s == '$')
		max = lastart;
	    else if (*s == '.')
		max = oldart;
	    else
		max = atol(s);
	}
	else
	    max = min;
	if (max>lastart) {
	    max = lastart;
	    if (min > max)
		min = max;
	    printf("(Last article is %ld)\n",(long)lastart);
	    pad(just_a_sec/3);
	}
	if (max < min) {
	    fputs("\nBad range\n",stdout);
	    if (cmdlst)
		free(cmdlst);
	    return NN_ASK;
	}
	if (justone) {
	    art = min;
	    return NN_REREAD;
	}
	check_first(min);
	for (art=min; art<=max; art++) {
	    if (perform(cmdlst,TRUE)) {
#ifdef VERBOSE
		IF(verbose)
		    printf("\n(Interrupted at article %ld)\n",(long)art);
		ELSE
#endif
#ifdef TERSE
		    printf("\n(Intr at %ld)\n",(long)art);
#endif
		if (cmdlst)
		    free(cmdlst);
		return NN_ASK;
	    }
	}
    }
    art = oldart;
    if (cmdlst)
	free(cmdlst);
    return NN_NORM;
}

int
perform(cmdlst,toplevel)
register char *cmdlst;
int toplevel;
{
    register int ch;
    
    if (toplevel) {
	printf("%-6ld",art);
	fflush(stdout);
    }
    for (; ch = *cmdlst; cmdlst++) {
	if (isspace(ch) || ch == ':')
	    continue;
	if (ch == 'j') {
	    mark_as_read(art);
#ifdef VERBOSE
		IF(verbose)
		    fputs("\tJunked",stdout);
#endif
	}
	else if (ch == 'm') {
	    unmark_as_read(art);
#ifdef VERBOSE
		IF(verbose)
		    fputs("\tMarked unread",stdout);
#endif
	}
	else if (ch == 'M') {
#ifdef DELAYMARK
	    delay_unmark(art);
#ifdef VERBOSE
		IF(verbose)
		    fputs("\tWill return",stdout);
#endif
#else
	    notincl("M");
	    return -1;
#endif
	}
	else if (ch == '=') {
	    printf("\t%s",fetchsubj(art,FALSE,FALSE));
#ifdef VERBOSE
	    IF(verbose)
		;
	    ELSE
#endif
		putchar('\n');		/* ghad! */
	}
	else if (ch == 'C') {
#ifdef ASYNC_PARSE
	    printf("\t%sancelled",(cancel_article() ? "Not c" : "C"));
#else
	    notincl("C");
	    return -1;
#endif
	}
	else if (ch == '%') {
#ifdef ASYNC_PARSE
	    char tmpbuf[512];

	    cmdlst = dointerp(tmpbuf,cmdlst,":");
	    if (*cmdlst != ':')
		--cmdlst;
	    if (perform(tmpbuf,FALSE))
		return -1;
#else
	    notincl("%");
	    return -1;
#endif
	}
	else if (index("!&sSwW|",ch)) {
	    cmdlst = cpytill(buf,cmdlst,':') - 1;
	    /* we now have the command in buf */
	    if (ch == '!') {
		escapade();
#ifdef VERBOSE
		IF(verbose)
		    fputs("\tShell escaped",stdout);
#endif
	    }
	    else if (ch == '&') {
		switcheroo();
#ifdef VERBOSE
		IF(verbose)
		    fputs("\tSwitched",stdout);
#endif
	    }
	    else {
		putchar('\t');
		save_article();
	    }
	}
	else {
	    printf("\t???%s\n",cmdlst);
	    return -1;
	}
#ifdef VERBOSE
	fflush(stdout);
#endif
    }
    if (toplevel) {
#ifdef VERBOSE
	IF(verbose)
	    putchar('\n');
	ELSE
#endif
#ifdef TERSE
	    putchar(' ');
#endif
    }
    return 0;
}

!STUFFY!FUNK!
echo Extracting kfile.c
cat >kfile.c <<'!STUFFY!FUNK!'
/* $Header: kfile.c,v 4.1 84/09/24 11:58:18 lwall Exp $
 *
 * $Log:	kfile.c,v $
 * Revision 4.1  84/09/24  11:58:18  lwall
 * Real baseline.
 * 
 * Revision 4.0.1.6  84/09/24  10:42:22  lwall
 * mention() did not terminate highlighting correctly.
 * 
 * Revision 4.0.1.5  84/09/14  08:54:53  lwall
 * kf_append did not append a newline.
 * 
 * Revision 4.0.1.4  84/09/13  12:04:57  lwall
 * UNLINK for Eunice.
 * 
 * Revision 4.0.1.3  84/09/10  15:15:58  lwall
 * Delinted.
 * 
 * Revision 4.0.1.2  84/09/06  17:02:30  lwall
 * Implemented newsgroup exit commands.
 * 
 * Revision 4.0.1.1  84/09/04  12:15:59  lwall
 * Allow switch setting (via &) in KILL files.
 * 
 * Revision 4.0  84/09/04  09:50:56  lwall
 * Baseline for netwide release
 * 
 */

#include "EXTERN.h"
#include "common.h"
#include "term.h"
#include "util.h"
#include "artsrch.h"
#include "ng.h"
#include "bits.h"
#include "intrp.h"
#include "ngstuff.h"
#include "INTERN.h"
#include "kfile.h"

static bool exitcmds = FALSE;

void
kfile_init()
{
    ;
}

#ifndef KILLFILES
int
edit_kfile()
{
    notincl("^K");
    return -1;
}

#else KILLFILES

char killglobal[] = KILLGLOBAL;
char killlocal[] = KILLLOCAL;

void
mention(str)
char *str;
{
#ifdef NOFIREWORKS
    no_sofire();
#endif
    standout();
    fputs(str,stdout);
    un_standout();
    putchar('\n');
    fflush(stdout);
}

int
do_kfile(kfp,entering)
FILE *kfp;
int entering;
{
    art = lastart+1;
    fseek(kfp,0L,0);			/* rewind file */
    while (fgets(buf,LBUFLEN,kfp) != Nullch) {
	buf[strlen(buf)-1] = '\0';
	if (strnEQ(buf,"THRU",4)) {
	    firstart = atol(buf+4)+1;
	    continue;
	}
	if (*buf == 'X') {		/* exit command? */
	    if (entering) {
		exitcmds = TRUE;
		continue;
	    }
	    strcpy(buf,buf+1);
	}
	else {
	    if (!entering)
		continue;
	}
	if (*buf == '&') {
	    mention(buf);
	    switcheroo();
	}
	else if (*buf == '/' && firstart <= lastart) {
	    mention(buf);
	    switch (art_search(buf,FALSE)) {
	    case SRCH_ABORT:
		continue;
	    case SRCH_INTR:
#ifdef VERBOSE
		IF(verbose)
		    printf("\n(Interrupted at article %ld)\n",(long)art);
		ELSE
#endif
#ifdef TERSE
		    printf("\n(Intr at %ld)\n",(long)art);
#endif
		return -1;
	    case SRCH_DONE:
		break;
	    case SRCH_SUBJDONE:
		fputs("\tsubject not found (???)\n",stdout);
		break;
	    case SRCH_NOTFOUND:
		fputs("\tnot found\n",stdout);
		break;
	    case SRCH_FOUND:
		fputs("\tfound\n",stdout);
	    }
	}
    }
    return 0;
}

void
kill_unwanted(starting,message,entering)
ART_NUM starting;
char *message;
int entering;
{
    bool intr = FALSE;			/* did we get an interrupt? */
    ART_NUM oldfirst;

    if (localkfp || globkfp) {
	if (!entering && !exitcmds)
	    return;
	exitcmds = FALSE;
	oldfirst = firstart;
	firstart = starting;
	clear();
	if (message)
	    fputs(message,stdout);
	if (localkfp)
	    intr = do_kfile(localkfp,entering);
	if (globkfp && !intr)
	    intr = do_kfile(globkfp,entering);
	if (entering && localkfp && !intr)
	    setthru(lastart);
	putchar('\n');
	if (entering)
	    get_anything();
	forcelast = FALSE;
	firstart = oldfirst;
    }
}

void
setthru(thru)
ART_NUM thru;
{
    FILE *newkfp;

    fseek(localkfp,0L,0);		/* rewind current file */
    strcpy(buf,filexp(getval("KILLLOCAL",killlocal)));
    UNLINK(buf);			/* to prevent file reuse */
    if (newkfp = fopen(buf,"w")) {
	fprintf(newkfp,"THRU %ld\n",(long)thru);
	while (fgets(buf,LBUFLEN,localkfp) != Nullch) {
	    if (strnEQ(buf,"THRU",4))
		continue;
	    fputs(buf,newkfp);
	}
	fclose(newkfp);
	open_kfile(KF_LOCAL);		/* and reopen local file */
    }
}

/* edit KILL file for newsgroup */

int
edit_kfile()
{
    int r = -1;

    if (in_ng)
	strcpy(buf,filexp(getval("KILLLOCAL",killlocal)));
    else
	strcpy(buf,filexp(getval("KILLGLOBAL",killglobal)));
    if ((r = makedir(buf,MD_FILE)) >= 0) {
	sprintf(cmd_buf,"%s %s",
	    filexp(getval("VISUAL",getval("EDITOR",defeditor))),buf);
	printf("\nEditing %s KILL file:\n%s\n",
	    (in_ng?"local":"global"),cmd_buf);
	resetty();			/* make sure tty is friendly */
	r = doshell(sh,cmd_buf);/* invoke the shell */
	noecho();			/* and make terminal */
	crmode();			/*   unfriendly again */
	open_kfile(in_ng);
    }
    else
	printf("Can't make %s\n",buf);
    return r;
}

void
open_kfile(local)
int local;
{
    char *kname = filexp(local ?
	getval("KILLLOCAL",killlocal) :
	getval("KILLGLOBAL",killglobal)
	);
    
    stat(kname,&filestat);
    if (!filestat.st_size)		/* nothing in the file? */
	UNLINK(kname);			/* delete the file */
    if (local) {
	if (localkfp)
	    fclose(localkfp);
	localkfp = fopen(kname,"r");
    }
    else {
	if (globkfp)
	    fclose(globkfp);
	globkfp = fopen(kname,"r");
    }
}

void
kf_append(cmd)
char *cmd;
{
    strcpy(cmd_buf,filexp(getval("KILLLOCAL",killlocal)));
    if (makedir(cmd_buf,MD_FILE) >= 0) {
#ifdef VERBOSE
	IF(verbose)
	    printf("\nDepositing command in %s...",cmd_buf);
	ELSE
#endif
#ifdef TERSE
	    printf("\n--> %s...",cmd_buf);
#endif
	fflush(stdout);
	sleep(2);
	if ((tmpfp = fopen(cmd_buf,"a")) != Nullfp) {
	    fseek(tmpfp,0L,2);		/* get to EOF for sure */
	    fprintf(tmpfp,"%s\n",cmd);
	    fclose(tmpfp);
	    fputs("done\n",stdout);
	}
	else
	    fputs("ERROR\n",stdout);
    }
}
#endif KILLFILES
!STUFFY!FUNK!
echo Extracting Rnmail.SH
cat >Rnmail.SH <<'!STUFFY!FUNK!'
case $CONFIG in
    '') . config.sh ;;
esac
echo "Extracting Rnmail (with variable substitutions)"
$spitshell >Rnmail <<!GROK!THIS!
#! /bin/sh
# $Header: Rnmail.SH,v 4.1 84/09/24 11:38:51 lwall Exp $
# 
# $Log:	Rnmail.SH,v $
# Revision 4.1  84/09/24  11:38:51  lwall
# Real baseline.
# 
# Revision 4.0.1.2  84/09/12  15:18:54  lwall
# Check for sh interpretation.
# 
# Revision 4.0.1.1  84/09/04  10:56:18  lwall
# Added possibility of using /usr/lib/news/recmail.
# 
# Revision 4.0  84/09/04  09:49:08  lwall
# Baseline for netwide release
# 
#
# syntax: Rnmail -h headerfile [oldart]		or
#         Rnmail destination-list 		or just
#         Rnmail

export PATH || (echo "OOPS, this isn't sh.  Desperation time.  I will feed myself to sh."; sh \$0; kill \$\$)

# System dependencies

mailer="${mailer-/bin/mail}"
# if you change this to something that does signatures, take out signature code

# your site name
sitename="$sitename"
# your organization name
orgname="$orgname"
# what pager you use--if you have kernal paging use cat
pager="$pager"
# how you derive full names, bsd, usg, or other
nametype="$nametype"
# default editor
defeditor="$defeditor"
# how not to do a newline with echo
n="$n"
c="$c"

test=${test-test}
sed=${sed-sed}
echo=${echo-echo}
cat=${cat-cat}
grep=${grep-grep}
rm=${rm-rm}

!GROK!THIS!
$spitshell >>Rnmail <<'!NO!SUBS!'
tmpart=/tmp/rnmail$$
dotdir=${DOTDIR-${HOME-$LOGDIR}}

headerfile=""
case $# in
0) ;;
*)  case $1 in
    -h)
	headerfile="$2"
	case $# in
	3) oldart=$3 ;;
	esac
	;;
    esac
    ;;
esac

case $headerfile in
'')
    case $# in
    0)
	to=h
	while $test "$to" = h ; do
	    $echo ""
	    $echo -n "To: "
	    read to
	    case $to in
	    h)
		$cat <<'EOH'

Type the net address of those people that you wish the message sent to.
Note that you will be asked later for additional addresses of people to
whom the message is not addressed but you wish to get copies.

Separate multiple addresses with spaces.

EOH
		;;
	    esac
	done
	;;
    *)
	to="$*"
	;;
    esac
    to=`$echo "$to" | $sed 's/  */ /g'`

    title=h
    while $test "$title" = h ; do
	$echo ""
	$echo -n "Title/Subject: "
	read title
	case $title in
	h)
	    $cat <<'EOH'

Type the title for your message.  
EOH
	    ;;
	esac
    done

# now build a file with a header for them to edit
    
    orgname=${ORGANIZATION-$orgname}
    case $orgname in
    /*) orgname=`$cat $orgname` ;;
    esac

    $cat > $tmpart <<EOHeader
To: $to
Subject: $title
Organization: $orgname
Cc:
Bcc:

EOHeader

    ;;
*)
    $cat < $headerfile  > $tmpart
    ;;
esac


file=h
while $test "$file" = h ; do
    $echo ""
    $echo -n "Input file name?  [RETURN for new file]: "
    read file
    case $file in
    h)
	$cat <<'EOH'

If you have already produced the body of your message, type the filename
for it here.  If you just want to proceed directly to the editor, type a
RETURN.  In any event, you will be allowed to edit as many times as you
want before you send off the message.
EOH
	;;
    '')
	$echo "" >> $tmpart
	state=edit
	;;
    *)
	$cat $file >>$tmpart
	state=ask
	;;
    esac
done

$echo ""

while true ; do
    case $state in
    edit)
	rescue="sleep 1; $cat $tmpart >>${HOME-$LOGDIR}/dead.letter ; $echo saved in ${HOME-$LOGDIR}/dead.letter ; $rm -f $tmpart; exit"
	trap "$rescue" 1
	trap "" 2
	tmp=h
	while $test "$tmp" = h ; do
	    $echo -n "Editor [${VISUAL-${EDITOR-$defeditor}}]: "
	    read tmp
	    case $tmp in
	    h)
		$cat <<'EOH'

Type a return to get the default editor, or type the name of the editor you
prefer.  The default editor depends on the VISUAL and EDITOR environment
variables.

EOH
		;;
	    '')
		;;
	    *)
		VISUAL=$tmp
		export VISUAL
		;;
	    esac
	done
	${VISUAL-${EDITOR-$defeditor}} $tmpart $oldart
	trap "$rescue" 2
	state=ask
	;;
	
    ask)
	$echo ""
	$echo -n "Send, abort, edit, or list? "
	read ans
	
	case $ans in
	a*)
	    state=rescue
	    ;;
	e*)
	    state=edit
	    ;;
	l*)
	    $pager $tmpart
	    state=ask
	    ;;
	s*)
	    state=send
	    ;;
	h*)
	    $cat <<'EOH'

Type s to send the message, a to abort and append the message to dead.letter,
e to edit the message again, or l to list the message.
EOH
	esac
	;;
    
    send)
	if $test -f $dotdir/.signature; then
	    echo $n "Append .signature file? [y] $c"
	    read ans
	    case $ans in
	    ''|y*) cat $dotdir/.signature >> $tmpart
	    esac
	fi
	case $mailer in
	*sendmail)
	    $mailer -t <$tmpart
	    ;;
# but recmail does not know about Bcc, alas
	*recmail)
	    $mailer <$tmpart
	    ;;
	*)
	    set `$sed <$tmpart -n -e '/^To:/{' -e 's/To: *//p' -e q -e '}'`
	    set "$@" `$sed <$tmpart -n -e '/^Cc:/{' -e 's/Cc: *//p' -e q -e '}'`
	    set "$@" `$sed <$tmpart -n -e '/^Bcc:/{' -e 's/Bcc: *//p' -e q -e '}'`
	    $grep -v "^Bcc:"  <$tmpart | $mailer "$@"
	    ;;
	esac
	case $? in
	0)
	    state=cleanup
	    ;;
	*)
	    state=rescue
	    ;;
	esac
	;;
    rescue)
	$cat $tmpart >> ${HOME-$LOGDIR}/dead.letter
	$echo "Message saved to ${HOME-$LOGDIR}/dead.letter"
	state=cleanup
	;;
    cleanup)
	$rm -f $tmpart
	exit
	;;
    esac
done
!NO!SUBS!
$eunicefix Rnmail
chmod 755 Rnmail
!STUFFY!FUNK!
echo Extracting README
cat >README <<'!STUFFY!FUNK!'
			Rn Kit, Version 4.1

		    Copyright (c) 1984, Larry Wall

You may copy the rn kit as long as you aren't trying to make money off it.
--------------------------------------------------------------------------
(Note: Berkeleyphiles and -phobes:  The 4.1 above is unrelated to 4.1bsd.)

Please read all the directions below before you proceed any further, and
then follow them carefully.  Failure to do so may void your warranty. :-)

After you have unpacked your kit, you should have all the files listed
in MANIFEST.

Installation

1)  Run Configure.  This will figure out various things about your system.
    Some things Configure will figure out for itself, other things it will
    ask you about.  It will then procede to make config.h, config.sh, Makefile,
    and a bunch of shell scripts.  It will also do a make depend for you.
    You might possibly have to trim # comments from the front of Configure
    if your sh doesn't handle them, but all other # comments will be taken
    care of.

2)  Glance through config.h and common.h to make sure system dependencies
    are correct.  Most of them should have been taken care of by running
    the Configure script.

    If you have any additional changes to make to the C definitions, they
    can be done in the Makefile, in config.h, or in common.h.  If you have
    strange mailboxes on your system you should modify mbox.saver to correctly
    append an article to a mailbox or folder.

    If you are on a machine with limited address space, you may have to
    remove some of the special functions of rn to make it fit.  This is
    easily done by undefining symbols in the System Dependencies section
    of common.h.  You should run "make depend" again to be safe.

3)  make

    This will attempt to make rn in the current directory.

4)  make install

    This will put rn, newsetup, newsgroups, Pnews, and Rnmail into a public
    directory (normally /usr/local/bin), and put a number of files into the
    private rn library (normally /usr/lib/news/rn).  It will also try to put
    the man pages in a reasonable place.

5)  Read the manual entry before running rn.  It's quite different from
    readnews.

6)  Install the Xref patch to header.h, header.c, and inews.c.  These patches
    are found in header.h.pat, header.c.pat, and inews.c.?.pat, where ? is
    either 1 for news 2.10.1 (or earlier) or 2 for 2.10.2.  The purpose
    of the Xref patch is to put an Xref: line in the header of articles
    posted to more than one newsgroup.  Rn uses this line to keep from showing
    such postings more than once.  Other than that rn will work without
    this patch, so if you just want to try out rn you can delay putting in
    the patch.

    When you put in the patch and recompile inews, don't forget to define
    DOXREFS in the makefile for inews.  Do NOT define LINKART unless you
    are a Eunice site and really want to do that.  In fact, if you are not
    a Eunice site you needn't install the LINKART part of the patch.

    NOTE: the Makefile that comes with some of the older news systems does not
    have all the dependencies quite right.  In particular, ifuncs.c may
    not recompile when you change header.h.  If this happens when you install
    the Xref patch, inews will start dumping core.  Make sure both inews.o
    and ifuncs.o depend on header.h in the Makefile.

    Eunice users: the inews.c patch contains both the Xref patch and a LINKART
    patch to put a form of "symbolic link" between articles posted to
    multiple newsgroups.  What it does is to put the article into the first
    newsgroup on the Newsgroups line, and in subsequent newsgroups it just
    puts a little file containing the name of the article in the first
    newsgroup.  Rn (when compiled with the LINKART option) is clever about
    these pseudo-articles, and ends up opening the right one.  YOU WILL NOT
    be able to use readnews or vnews on your system without modification,
    though.  If you do this, be sure to define both DOXREFS and LINKART in
    the makefile for inews.c.  If you are using the option in inews that
    copies instead of linking, you will want to rip that out.

    NOTE: if you transmit articles to other systems using xfernews with the
    U flag, Xref's can leak out of your system, as can Date-Received's.  This
    may make neighboring sites unhappy unless they also have the Xref patch
    installed.  For now, either don't use the U flag, or fix the inews/xfernews
    interaction.

7)  Try rn, and play with some of the switches.  You may want to make -/
    default on your system.  This is done in common.h.  You may want to modify
    which header lines are displayed by default--this is done in head.h.

8)  IMPORTANT!  Help save the world!  Communicate any problems and
    suggested patches to me, lwall@sdcrdcf.UUCP (Larry Wall), so we can
    keep the world in sync.  If you have a problem, there's someone else
    out there who either has had or will have the same problem.

9)  If you are going to hack on rn, please read the HACKERSGUIDE first.
!STUFFY!FUNK!
echo Extracting term.h
cat >term.h <<'!STUFFY!FUNK!'
/* $Header: term.h,v 4.1 84/09/24 12:11:06 lwall Exp $
 *
 * $Log:	term.h,v $
 * Revision 4.1  84/09/24  12:11:06  lwall
 * Real baseline.
 * 
 * Revision 4.0.1.2  84/09/12  17:21:34  lwall
 * Little TERMIO bug.
 * 
 * Revision 4.0.1.1  84/09/10  15:34:07  lwall
 * Delinted.
 * 
 * Revision 4.0  84/09/04  09:52:57  lwall
 * Baseline for netwide release
 * 
 */

#ifdef PENDING
#ifdef FIONREAD	/* must have FIONREAD or O_NDELAY for input_pending() */
#define read_tty(addr,size) read(0,addr,size)
#define input_pending() (ioctl(0, FIONREAD, &iocount),(int)iocount)
EXT long iocount INIT(0);

#else

#include <fcntl.h>
EXT int devtty INIT(0);
EXT bool is_input INIT(FALSE);
EXT char pending_ch INIT(0);
#define input_pending() (is_input?TRUE:(is_input=read(devtty,&pending_ch,1)))
#endif
#else
#define read_tty(addr,size) read(0,addr,size)
#define input_pending() (FALSE)
#endif

/* stuff wanted by terminal mode diddling routines */

#ifdef TERMIO
EXT struct termio _tty, _oldtty;
#else
EXT struct sgttyb _tty;
EXT int _res_flg INIT(0);
#endif

EXT int _tty_ch INIT(2);
EXT bool bizarre INIT(FALSE);			/* do we need to restore terminal? */

/* terminal mode diddling routines */

#ifdef TERMIO

#define crmode() ((bizarre=1),_tty.c_lflag &=~ICANON,_tty.c_cc[VMIN] = 1,ioctl(_tty_ch,TCSETAF,&_tty))
#define nocrmode() ((bizarre=1),_tty.c_lflag |= ICANON,_tty.c_cc[VEOF] = CEOF,stty(_tty_ch,&_tty))
#define echo()	 ((bizarre=1),_tty.c_lflag |= ECHO, ioctl(_tty_ch, TCSETA, &_tty))
#define noecho() ((bizarre=1),_tty.c_lflag &=~ECHO, ioctl(_tty_ch, TCSETA, &_tty))
#define nl()	 ((bizarre=1),_tty.c_iflag |= ICRNL,_tty.c_oflag |= ONLCR,ioctl(_tty_ch, TCSETAW, &_tty))
#define nonl()	 ((bizarre=1),_tty.c_iflag &=~ICRNL,_tty.c_oflag &=~ONLCR,ioctl(_tty_ch, TCSETAW, &_tty))
#define	savetty() ((bizarre=1),ioctl(_tty_ch, TCGETA, &_oldtty),ioctl(_tty_ch, TCGETA, &_tty))
#define	resetty() ((bizarre=0),ioctl(_tty_ch, TCSETAF, &_oldtty))

#else

#define raw()	 ((bizarre=1),_tty.sg_flags|=RAW, stty(_tty_ch,&_tty))
#define noraw()	 ((bizarre=1),_tty.sg_flags&=~RAW,stty(_tty_ch,&_tty))
#define crmode() ((bizarre=1),_tty.sg_flags |= CBREAK, stty(_tty_ch,&_tty))
#define nocrmode() ((bizarre=1),_tty.sg_flags &= ~CBREAK,stty(_tty_ch,&_tty))
#define echo()	 ((bizarre=1),_tty.sg_flags |= ECHO, stty(_tty_ch, &_tty))
#define noecho() ((bizarre=1),_tty.sg_flags &= ~ECHO, stty(_tty_ch, &_tty))
#define nl()	 ((bizarre=1),_tty.sg_flags |= CRMOD,stty(_tty_ch, &_tty))
#define nonl()	 ((bizarre=1),_tty.sg_flags &= ~CRMOD, stty(_tty_ch, &_tty))
#define	savetty() ((bizarre=1),gtty(_tty_ch, &_tty), _res_flg = _tty.sg_flags)
#define	resetty() ((bizarre=0),_tty.sg_flags = _res_flg, stty(_tty_ch, &_tty))
#endif

#ifdef TIOCSTI
#define forceme(c) ioctl(_tty_ch,TIOCSTI,c) /* pass character in " " */
#else
#define forceme(c)
#endif

/* termcap stuff */

/*
 * NOTE: if you don't have termlib you'll either have to define these strings
 *    and the tputs routine, or you'll have to redefine the macros below
 */

#ifdef HAVETERMLIB
EXT char *BC INIT(Nullch);		/* backspace character */
EXT char *UP INIT(Nullch);		/* move cursor up one line */
EXT char *CL INIT(Nullch);		/* home and clear screen */
EXT char *CE INIT(Nullch);		/* clear to end of line */
EXT char *SO INIT(Nullch);		/* begin standout mode */
EXT char *SE INIT(Nullch);		/* end standout mode */
EXT int SG INIT(0);		/* blanks left by SO and SE */
EXT char *US INIT(Nullch);		/* start underline mode */
EXT char *UE INIT(Nullch);		/* end underline mode */
EXT char *UC INIT(Nullch);		/* underline a character, if that's how it's done */
EXT int UG INIT(0);		/* blanks left by US and UE */
EXT bool AM INIT(FALSE);		/* does terminal have automatic margins? */
EXT bool XN INIT(FALSE);		/* does it eat 1st newline after automatic wrap? */
EXT char PC INIT(0);		/* pad character for use by tputs() */
EXT short ospeed INIT(0);	/* terminal output speed, for use by tputs() */
EXT int LINES INIT(0), COLS INIT(0);	/* size of screen */
EXT int just_a_sec INIT(960);			/* 1 sec at current baud rate */
					/* (number of nulls) */

/* define a few handy macros */

#define backspace() tputs(BC,0,putchr)
#define clear() tputs(CL,LINES,putchr)
#define erase_eol() tputs(CE,1,putchr)
#define underline() tputs(US,1,putchr)
#define un_underline() tputs(UE,1,putchr)
#define underchar() tputs(UC,0,putchr)
#define standout() tputs(SO,1,putchr)
#define un_standout() tputs(SE,1,putchr)
#define up_line() tputs(UP,1,putchr)
#else
  ????????		/* up to you */
#endif

EXT int page_line INIT(1);	/* line number for paging in print_line (origin 1) */

void	term_init();
char	putchr();	/* routine for tputs to call */
bool	finish_command();
void	eat_typeahead();
#ifndef read_tty
    int		read_tty();
#endif
void	underprint();
#ifdef NOFIREWORKS
    void	no_sofire();
    void	no_ulfire();
#endif
void	getcmd();
int	get_anything();
void	in_char();
int	print_lines();
void	pad();
void	printcmd();
void	rubout();
void	reprint();
!STUFFY!FUNK!
echo Extracting HACKERSGUIDE
cat >HACKERSGUIDE <<'!STUFFY!FUNK!'
Hacking Notes

If you aren't interested in mucking with the innards of rn, don't read this.

In the interests of both space and time optimization, things are done inside
rn that don't always conform to the highest ideals of programming.  To the
extent I felt it was practical, I've tried to conform to good programming
practice, but you must realize that my goal was to make a better mousetrap,
so certain conscious tradeoffs were made in the design of rn right from the
start.  In particular, if you want to hack on rn (and I wouldn't blame you,
it's fun), beware of the following:
  
  * buf and cmd_buf are reused all over the place.  11-squishing is a good
    term for it.  No, I'm on a Vax now, but I've been there.

  * The article header is parsed on the fly, while it is being displayed.
    In fact, practically everything is done on the fly within the article
    display loop, and there are plenty of state variables.  The header
    is never explicitly stored in memory; rather, pointers are kept into
    the file.  The information required to backup pages is not stored in
    memory, except for 1 buffer's worth.  The information required to do
    the delayed mark as unread (M) is not stored in memory either.

  * Lots of contortions are gone through to avoid using static memory, or
    allocating unnecessary memory, or losing track of allocated memory,
    while at the same time allowing .newsrc lines and header lines to be
    ANY length up to the amount of memory you have.  Rn spends a great deal
    of effort being lazy.  Do not use a static buffer when you can use
    growstr().

  * Lots of contortions are gone through to try to do things when people
    aren't waiting, or have only been waiting a very short time.  Guessing
    the next article to be opened and opening it, searching ahead for the
    next article with the same subject, delaying the look up of the number
    of articles in a newsgroup, writing the rest of the page while the
    reader is examining the header, cacheing up subjects while the user
    is reading, checkpointing the .newsrc only while the reader is in the
    middle of an interesting article, are some of the strategies employed.
  
  * There are plenty of goto's.  Most of them involve going back to reprompt,
    to reask for input, or to just plain do the unstructured things people
    want to do when they are glaring at a terminal.  If they bother you
    too much, just think of rn as a big state machine.  If they don't bother
    you at all, I don't want you hacking on rn.

  * Put all includes at the front of the file, before the first function,
    or makedepend will not work right.  I could relax this, but makedepend
    would take about 5 times longer to run.

In general then, feel free to hack on rn.  Just don't broadcast untested
patches to the net.  Remember that there are people with limited address
spaces and limited cpu cycles.  If you add a wonderful new feature and
want to publish a patch, put #ifdef's around it so that people who don't
want it or can't afford it can work around it.  THIS MEANS YOU.  We don't
need 57 varieties of mutually incompatible and incomprehensible rn floating
about the net.  Consider telling me about your patch so that I can consider
including it in the standard version.  A COMPLETE PATCH TAKES INTO ACCOUNT
SYSTEM DEPENDENCIES AS DETERMINED BY THE CONFIGURE SCRIPT.

* Don't use ints where rn uses typedefs, in particular, for article numbers.
* Don't use %d anywhere that someone might need a %ld.  (Just because YOU
    typedefed it as an int doesn't mean someone else won't need a long.)
* Don't use %D, that's archaic.
* Declare the type of every function.  Use void, even if your C compiler
    doesn't.
* Follow the style that rn already uses!  This is my pet peeve.  Well, one of
    them, anyway.  I follow other people's strange styles when modifying
    their programs, so I'd be much obliged if you did likewise.
* Use lint.
* Use RCS.  Start a new branch, like 4.1.[2-9].  (I will use 4.1.1 myself.)
* Be structured wherever it doesn't interfere with practicality.
* Long live paranoid programming.  The rest of the program is out to get you.
    The world is out to destroy the program, not to mention the .newsrc.
    And then there's always bitrot...
* Stop reading this lugubrious trash and start thinking for yourself.
* Thank you and good night.
!STUFFY!FUNK!
echo Extracting Makefile.SH
cat >Makefile.SH <<'!STUFFY!FUNK!'
case $CONFIG in
    '') . config.sh ;;
esac
echo "Extracting Makefile (with variable substitutions)"
cat >Makefile <<!GROK!THIS!
# $Header: Makefile.SH,v 4.1 84/09/24 11:37:35 lwall Exp $
#
# $Log:	Makefile.SH,v $
# Revision 4.1  84/09/24  11:37:35  lwall
# Real baseline.
# 
# Revision 4.0.1.4  84/09/12  16:57:01  lwall
# Added ndir.
# 
# Revision 4.0.1.3  84/09/12  15:16:38  lwall
# Check for sh on install.
# 
# Revision 4.0.1.2  84/09/06  14:01:35  lwall
# Made not install newsnews over existent one.
# 
# Revision 4.0.1.1  84/09/06  13:15:19  lwall
# General cleanup.
# 
# Revision 4.0  84/09/04  09:48:44  lwall
# Baseline for netwide release
# 

rnbin = $rnbin
rnlib = $rnlib
mansrc = $mansrc
CFLAGS = $iandd -O
LDFLAGS = $iandd

libs = $ndirlib $termlib $jobslib
!GROK!THIS!
cat >>Makefile <<'!NO!SUBS!'

public = rn newsetup newsgroups Pnews Rnmail
private = norm.saver mbox.saver ng.help art.help pager.help subs.help makedir filexp

h1 = addng.h art.h artio.h artsrch.h backpage.h bits.h cheat.h common.h
h2 = final.h head.h help.h init.h intrp.h kfile.h last.h ndir.h ng.h
h3 = ngdata.h ngsrch.h ngstuff.h only.h rcln.h rcstuff.h
h4 = respond.h rn.h search.h sw.h term.h util.h

h = $(h1) $(h2) $(h3) $(h4)

c1 = addng.c art.c artio.c artsrch.c backpage.c bits.c cheat.c
c2 = final.c head.c help.c init.c intrp.c kfile.c last.c ndir.c ng.c
c3 = ngdata.c ngsrch.c ngstuff.c only.c rcln.c rcstuff.c
c4 = respond.c rn.c search.c sw.c term.c util.c

c = $(c1) $(c2) $(c3) $(c4)

obj1 = addng.o art.o artio.o artsrch.o backpage.o bits.o cheat.o
obj2 = final.o head.o help.o init.o intrp.o kfile.o last.o ndir.o ng.o
obj3 = ngdata.o ngsrch.o ngstuff.o only.o rcln.o rcstuff.o
obj4 = respond.o rn.o search.o sw.o term.o util.o

obj = $(obj1) $(obj2) $(obj3) $(obj4)

lintflags = -phbvxac


.c.o:
	$(CC) -c $(CFLAGS) $*.c

rn: $(obj)
	$(CC) $(LDFLAGS) $(obj) $(libs) -o rn

# if a .h file depends on another .h file...
$(h):
	touch $@

install: rn
# won't work with csh
	export PATH || exit 1
	- mv $(rnbin)/rn $(rnbin)/rn.old
	- if test `pwd` != $(rnbin); then cp $(public) $(rnbin); fi
	cd $(rnbin); chmod 755 $(public)
	chmod 755 makedir
	- makedir `filexp $(rnlib)`
	- if test `pwd` != `filexp $(rnlib)`; then cp $(private) `filexp $(rnlib)`; fi
	cd `filexp $(rnlib)`; chmod 755 $(private)
	- if test ! -f `filexp $(rnlib)/newsnews`; then cp newsnews `filexp $(rnlib)`; fi
	- if test `pwd` != $(mansrc); then cp $(manpages) $(mansrc); fi

# The following lint has practically everything turned on.  Unfortunately,
# you have to wade through a lot of mumbo jumbo that can't be suppressed.
# If the source file has a /*NOSTRICT*/ somewhere, ignore the lint message
# for that spot.

lint:
	lint $(lintflags) $(defs) $(c) > rn.fuzz

depend:
	makedepend

# AUTOMATICALLY GENERATED MAKE DEPENDENCIES--PUT NOTHING BELOW THIS LINE
$(obj):
	@ echo "You haven't done a "'"make depend" yet!'; exit 1
!NO!SUBS!
$eunicefix Makefile
!STUFFY!FUNK!
echo ""
echo "End of kit 6 (of 8)"
cat /dev/null >kit6isdone
config=true
for iskit in 1 2 3 4 5 6 7 8; do
    if test -f kit${iskit}isdone; then
	echo "You have run kit ${iskit}."
    else
	echo "You still need to run kit ${iskit}."
	config=false
    fi
done
case $config in
    true)
	echo "You have run all your kits.  Please read README and then type Configure."
	chmod 755 Configure
	;;
esac
: I do not append .signature, but someone might mail this.
exit