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

echo "This is rn kit 7 (of 11).  If kit 7 is complete, the line"
echo '"'"End of kit 7 (of 11)"'" will echo at the end.'
echo ""
export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
echo Extracting rn.c
cat >rn.c <<'!STUFFY!FUNK!'
/*  rn -- new readnews program
 *
 *  Original Author: lwall@sdcrdcf.UUCP (Larry Wall)
 *  Organization: System Development Corporation, Santa Monica
 *  Current Author/Maintainer: sob@bcm.tmc.edu (Stan Barber)
 *  Organization: Baylor College of Medicine, Houston,Tx
 *
 *  begun:   01/14/83
 *	1.0: 04/08/83
 *      2.0: 09/01/83
 *      RRN/RN: 11/01/89
 *      4.4  07/04/91
 */
/* This software is Copyright 1991 by Stan Barber. 
 *
 * Permission is hereby granted to copy, reproduce, redistribute or otherwise
 * use this software as long as: there is no monetary profit gained
 * specifically from the use or reproduction of this software, it is not
 * sold, rented, traded or otherwise marketed, and this copyright notice is
 * included prominently in any copy made. 
 *
 * The author make no claims as to the fitness or correctness of this software
 * for any use whatsoever, and it is provided as is. Any use of this software
 * is at the user's own risk. 
 */

static char rnid[] = "@(#)$Id: rn.c,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $";
static char patchlevel[] = "Patchlevel 3";

/* $Log: rn.c,v $
 * Revision 4.4.3.1  1992/02/01  03:09:32  sob
 * Release 4.4 Patchlevel 3
 *
 * Revision 4.4.2.1  1991/12/01  18:05:42  sob
 * Patchlevel 2 changes
 *
 * Revision 4.4.1.1  1991/09/25  19:38:08  sob
 * Updated patchlevel message
 *
 * Revision 4.4  1991/09/09  20:27:37  sob
 * release 4.4
 *
 *
 *
 * 
 */

#include "INTERN.h"
#include "common.h"
#include "rn.h"
#ifdef SERVER
#include "server.h"
#endif
#include "EXTERN.h"
#include "rcstuff.h"
#include "term.h"
#include "final.h"
#include "search.h"
#include "ngdata.h"
#include "util.h"
#include "only.h"
#include "ngsrch.h"
#include "help.h"
#include "last.h"
#include "init.h"
#include "intrp.h"
#include "rcln.h"
#include "sw.h"
#include "addng.h"
#include "ng.h"

void
rn_init()
{
    ;
}

void
main(argc,argv)
int argc;
char *argv[];
{
    bool foundany;
    register char *s;
    bool oh_for_the_good_old_days = FALSE;
    int direction = 1;
    foundany = initialize(argc,argv);

    if (maxngtodo)
	starthere = 0;
    else if (!foundany) {		/* nothing to do? */
#ifdef VERBOSE
	if (verbose)
	    fputs("\
No unread news in subscribed-to newsgroups.  To subscribe to a new\n\
newsgroup use the g<newsgroup> command.\n\
",stdout) FLUSH;
#endif
	starthere = nextrcline;
    }

    /* loop through all unread news */

    {
	bool special = FALSE;		/* temporarily allow newsgroup */
					/*   with no unread news? */
	bool retry;			/* cycle back to top of list? */
	NG_NUM recent_ng = 0;
	
	current_ng = 0;
	do {
	    retry = FALSE;
	    if (findlast) {
		findlast = FALSE;
		starthere = 0;
		if (*lastngname) {
		    if ((ng = find_ng(lastngname)) == nextrcline)
			ng = 0;
		    else {
			set_ngname(lastngname);
		    	set_toread(ng);
			if (toread[ng] <= TR_NONE)
			    ng = 0;
		    }
		}
	    }
	    else {
		ng = starthere;
		starthere = 0;
	    }
	    while (ng <= nextrcline) {	/* for each newsgroup */
		mode = 'n';
		if (ng >= nextrcline) {	/* after the last newsgroup? */
		    ng = nextrcline;	/* force it to 1 after */
#ifdef ONLY
		    if (maxngtodo) {
			if (retry)
#ifdef VERBOSE
			    IF(verbose)
				printf("\nRestriction %s%s still in effect.\n",
				    ngtodo[0],
				    maxngtodo > 1 ? ", etc." : nullstr) FLUSH;
			    ELSE
#endif
#ifdef TERSE
				fputs("\n(\"Only\" mode.)\n",stdout) FLUSH;
#endif
			else {
#ifdef VERBOSE
			    IF(verbose)
				fputs("\nNo articles under restriction.",
				  stdout) FLUSH;
			    ELSE
#endif
#ifdef TERSE
				fputs("\nNo \"only\" articles.",stdout) FLUSH;
#endif
			    end_only();	/* release the restriction */
			    retry = TRUE;
			}
		    }
#endif
		}
		else {
		    bool shoe_fits;	/* newsgroup matches restriction? */

		    if (toread[ng] >= TR_NONE) {	/* recalc toread? */
			set_ngname(rcline[ng]);
			shoe_fits = inlist(ngname);
			if (shoe_fits)
			    set_toread(ng);
			if (paranoid) {
			    recent_ng = current_ng;
			    current_ng = ng;
			    cleanup_rc();
					/* this may move newsgroups around */
			    ng = current_ng;
			    set_ngname(rcline[ng]);
			}
		    }
		    if (toread[ng] < (maxngtodo||special ? TR_NONE : TR_ONE)
		     || !shoe_fits) {		/* unwanted newsgroup? */
			ng += direction;	/* then skip it */
			if (ng < 0) {
			   ng = 1;
			   direction = 1;
			}
			continue;
		    }
		}
		special = FALSE;	/* go back to normal mode */
		if (ng != current_ng) {
		    recent_ng = current_ng;
					/* remember previous newsgroup */
		    current_ng = ng;	/* remember current newsgroup */
		}
    reask_newsgroup:
		unflush_output();	/* disable any ^O in effect */
		if (ng >= nextrcline) {
#ifdef SERVER
		    if (time(Null(time_t*)) - lastactfetch > MINFETCHTIME) {
			fclose(actfp);
			ngdata_init();	/* re-grab the active file */
		    }
#endif
		    dfltcmd = (retry ? "npq" : "qnp");
#ifdef VERBOSE
		    IF(verbose)
			printf("\n******** End of newsgroups--what next? [%s] ",
			    dfltcmd);
		    ELSE
#endif
#ifdef TERSE
			printf("\n**** End--next? [%s] ", dfltcmd);
#endif
		} else {
		    dfltcmd = "ynq";
#ifdef VERBOSE
		    IF(verbose)
			printf("\n******** %3ld unread article%s in %s--read now? [%s] ",
			    (long)toread[ng], (toread[ng]==TR_ONE ? nullstr : "s"),
			    ngname, dfltcmd);
		    ELSE
#endif
#ifdef TERSE
			printf("\n**** %3ld in %s--read? [%s] ",
			    (long)toread[ng],
			    ngname,dfltcmd);
#endif
		}
		fflush(stdout);
    reinp_newsgroup:
		eat_typeahead();
		getcmd(buf);
		if (errno || *buf == '\f') {
		    putchar('\n') FLUSH; /* if return from stop signal */
		    goto reask_newsgroup;	/* give them a prompt again */
		}
		setdef(buf,dfltcmd);
#ifdef VERIFY
		printcmd();
#endif
		switch (*buf) {
		case 'P':		/* goto previous newsgroup */
		    special = TRUE;	/* don't skip it if toread==0 */
		    /* FALL THROUGH */
		case 'p':		/* find previous unread newsgroup */
		    if (ng > 0)
			ng--;
		    direction = -1;	/* go backward in the newsrc */
		    break;
		case '-':
		    ng = recent_ng;	/* recall previous newsgroup */
		    if (ng < nextrcline)
			if (!get_ng(rcline[ng],FALSE))
			    ng = current_ng;
		    special = TRUE;	/* don't skip it if toread==0 */
		    break;
		case 'q': case 'Q': case 'x':	/* quit? */
		    oh_for_the_good_old_days = (*buf == 'x');
		    putchar('\n') FLUSH;
		    ng = nextrcline+1;	/* satisfy */
		    retry = FALSE;	/*   loop conditions */
		    break;
		case '^':
		    putchar('\n') FLUSH;
		    ng = 0;
		    break;
		case 'n':		/* find next unread newsgroup */
		    if (ng == nextrcline) {
			putchar('\n') FLUSH;
			retry = TRUE;
		    }
		    else if (toread[ng] > TR_NONE)
			retry = TRUE;
		    ng++;
		    break;
		case 'N':		/* goto next newsgroup */
		    special = TRUE;	/* and don't skip it if toread==0 */
		    ng++;
		    break;
		case '1':		/* goto 1st newsgroup */
		    ng = 0;
		    special = TRUE;	/* and don't skip it if toread==0 */
		    break;
		case '$':
		    ng = nextrcline;	/* goto last newsgroup */
		    retry = TRUE;
		    break;
		case 'L':
		    list_newsgroups();
		    goto reask_newsgroup;
		case '/': case '?':	/* scan for newsgroup pattern */
#ifdef NGSEARCH
		    switch (ng_search(buf,TRUE)) {
		    case NGS_ERROR:
			goto reask_newsgroup;
		    case NGS_ABORT:
			goto reinp_newsgroup;
		    case NGS_INTR:
#ifdef VERBOSE
			IF(verbose)
			    fputs("\n(Interrupted)\n",stdout) FLUSH;
			ELSE
#endif
#ifdef TERSE
			    fputs("\n(Intr)\n",stdout) FLUSH;
#endif
			ng = current_ng;
			goto reask_newsgroup;
		    case NGS_FOUND:
			special = TRUE;	/* don't skip it if toread==0 */
			break;
		    case NGS_NOTFOUND:
#ifdef VERBOSE
			IF(verbose)
			    fputs("\n\nNot found--use a or g to add newsgroups\n",
				stdout) FLUSH;
			ELSE
#endif
#ifdef TERSE
			    fputs("\n\nNot found\n",stdout) FLUSH;
#endif
			goto reask_newsgroup;
		    }
#else
		    notincl("/");
#endif
		    break;
		case 'm':
#ifndef RELOCATE
		    notincl("m");
		    break;
#endif		    
		case 'g':	/* goto named newsgroup */
		    if (!finish_command(FALSE))
					/* if they didn't finish command */
			goto reinp_newsgroup;	/* go try something else */
		    for (s = buf+1; *s == ' '; s++);
					/* skip leading spaces */
#ifdef RELOCATE
		    if (!*s && *buf == 'm' && ngname && ng < nextrcline)
			strcpy(s,ngname);
#endif
		    if (isalpha(*s)) 
			set_ngname(s);
		    else {
			if (isdigit(*s)) {
			    int rcnum;
			    rcnum = atoi(s);
			    if (rcnum < nextrcline)
				set_ngname(rcline[rcnum]);
			    else {
				printf("\nOnly %d groups. Try again.\n",
					nextrcline) FLUSH;
				goto reask_newsgroup;
			    }
			}
			else {
			    printf("\nPlease specify a newsgroup.\n") FLUSH;
			    goto reask_newsgroup;
			}
		    }
#ifdef RELOCATE
		    if (!get_ng(ngname,*buf=='m'))
						/* try to find newsgroup */
#else
		    if (!get_ng(ngname,FALSE))	/* try to find newsgroup */
#endif
			ng = current_ng;/* if not found, go nowhere */
		    special = TRUE;	/* don't skip it if toread==0 */
		    break;
#ifdef DEBUGGING
		case 'D':
		    printf("\nTries: %d Hits: %d\n",
			softtries,softtries-softmisses) FLUSH;
		    goto reask_newsgroup;
#endif
		case '!':		/* shell escape */
		    if (escapade())	 /* do command */
			goto reinp_newsgroup;
					/* if rubbed out, re input */
		    goto reask_newsgroup;
		case Ctl('k'):		/* edit global KILL file */
		    edit_kfile();
		    goto reask_newsgroup;
		case 'c':		/* catch up */
#ifdef CATCHUP
reask_catchup:
#ifdef VERBOSE
		    IF(verbose)
			in_char("\nDo you really want to mark everything as read? [yn] ", 'C');
		    ELSE
#endif
#ifdef TERSE
			in_char("\nReally? [ynh] ", 'C');
#endif
		    setdef(buf,"y");
#ifdef VERIFY
		    printcmd();
#endif
		    putchar('\n') FLUSH;
		    if (*buf == 'h') {
#ifdef VERBOSE
			printf("Type y or SP to mark all articles as read.\n");
			printf("Type n to leave articles marked as they are.\n");
#else
			printf("y or SP to mark all read.\n");
			printf("n to forget it.\n");
#endif
			goto reask_catchup;
		    }
		    else if (*buf != 'y' && *buf != 'n' && *buf != 'q') {
			printf(hforhelp);
			settle_down();
			goto reask_catchup;
		    } else if (*buf == 'y' && ng<nextrcline)
			catch_up(ng);
		    else
			retry = TRUE;
		    ng++;
#else
		    notincl("c");
#endif
		    break;
		case 'u':		/* unsubscribe */
		    if (ng < nextrcline && toread[ng] >= TR_NONE) {
					/* unsubscribable? */
			printf(unsubto,rcline[ng]) FLUSH;
			rcchar[ng] = NEGCHAR;
					/* unsubscribe to (from?) it */
			toread[ng] = TR_UNSUB;
					/* and make line invisible */
			ng++;		/* do an automatic 'n' */
		    }
		    break;
		case 'h': {		/* help */
		    int cmd;

		    if ((cmd = help_ng()) > 0)
			pushchar(cmd);
		    goto reask_newsgroup;
		}
		case 'A':
		    if (ng >= nextrcline)
			break;
reask_abandon:
#ifdef VERBOSE
		    IF(verbose)
			in_char("\nAbandon changes to current newsgroup? [yn] ", 'B');
		    ELSE
#endif
#ifdef TERSE
			in_char("\nAbandon? [ynh] ", 'B');
#endif
		    setdef(buf,"y");
#ifdef VERIFY
		    printcmd();
#endif
		    putchar('\n') FLUSH;
		    if (*buf == 'h') {
#ifdef VERBOSE
			printf("Type y or SP to abandon the changes to this group since you started trn.\n");
			printf("Type n to leave the group as it is.\n");
#else
			printf("y or SP to abandon changes to this group.\n");
			printf("n to forget it.\n");
#endif
			goto reask_abandon;
		    }
		    else if (*buf != 'y' && *buf != 'n' && *buf != 'q') {
			printf(hforhelp);
			settle_down();
			goto reask_abandon;
		    } else if (*buf == 'y')
			abandon_ng(ng);
		    special = TRUE;	/* don't skip it if toread==0 */
		    break;
		case 'a':
#ifndef FINDNEWNG
		    notincl("a");
		    goto reask_newsgroup;
#else
		    addnewbydefault = 0;
		    /* FALL THROUGH */
#endif
		case 'o':
#ifdef ONLY
		{
#ifdef FINDNEWNG
		    bool doscan = (*buf == 'a');
#endif

		    if (!finish_command(TRUE)) /* get rest of command */
			goto reinp_newsgroup;	/* if rubbed out, try something else */
		    end_only();
		    if (buf[1]) {
			bool minusd = instr(buf+1,"-d", TRUE) != Nullch;

			sw_list(buf+1);
			if (minusd)
			    cwd_check();
			putchar('\n') FLUSH;
#ifdef FINDNEWNG
			if (doscan && maxngtodo)
			    scanactive();
#endif
		    }
		    ng = 0;		/* simulate ^ */
		    retry = FALSE;
		    break;
		}
#else
		    notincl("o");
		    goto reask_newsgroup;
#endif
		case '&':
		    if (switcheroo()) /* get rest of command */
			goto reinp_newsgroup;	/* if rubbed out, try something else */
		    goto reask_newsgroup;
		case 'l': {		/* list other newsgroups */
		    if (!finish_command(TRUE)) /* get rest of command */
			goto reinp_newsgroup;	/* if rubbed out, try something else */
		    for (s = buf+1; *s == ' '; s++);
		    			/* skip leading spaces */
		    sprintf(cmd_buf,"%s '%s'",filexp(NEWSGROUPS),s);
		    resetty();
		    if (doshell(sh,cmd_buf))
#ifdef VERBOSE
			IF(verbose)
			    fputs("    (Error from newsgroups program)\n",
				stdout) FLUSH;
			ELSE
#endif
#ifdef TERSE
			    fputs("(Error)\n",stdout) FLUSH;
#endif
		    noecho();
		    crmode();
		    goto reask_newsgroup;
		}
		case '.': case '=':
		case 'y': case 'Y': /* do normal thing */
		    if (ng >= nextrcline) {
			fputs("\nNot on a newsgroup.",stdout) FLUSH;
			goto reask_newsgroup;
		    }
		    if (*buf == '=')
			s = savestr("=");
		    else if (*buf == '.') {	/* start command? */
			if (!finish_command(FALSE)) /* get rest of command */
			    goto reinp_newsgroup;
			s = savestr(buf+1);
					/* do_newsgroup will free it */
		    }
		    else
			s = Nullch;
		    if (toread[ng])
			retry = TRUE;
		    switch (do_newsgroup(s)) {
		    case NG_ERROR:
		    case NG_NORM:
			ng++;
			break;
		    case NG_ASK:
			goto reask_newsgroup;
		    case NG_MINUS:
			ng = recent_ng;	/* recall previous newsgroup */
			special = TRUE;	/* don't skip it if toread==0 */
			break;
		    }
		    break;
#ifdef STRICTCR
		case '\n':
		    fputs(badcr,stdout) FLUSH;
		    goto reask_newsgroup;
#endif
		case 'v':
		    printf("\n%s",rnid);
		    printf("\n%s",patchlevel);
		    printf("\nSend bugs to rrn@lib.tmc.edu (...!uunet!bcm!rrn)\n") FLUSH;
		    goto reask_newsgroup;
		default:
		    printf("\n%s",hforhelp) FLUSH;
		    settle_down();
		    goto reask_newsgroup;
		}
	    }
	} while (retry);
    }

    /* now write .newsrc back out */

    write_rc();

    if (oh_for_the_good_old_days)
	get_old_rc();

    finalize(0);			/* and exit */
}

/* set current newsgroup */

void
set_ngname(what)
char *what;
{
    int len = strlen(what)+1;

    growstr(&ngname,&ngnlen,len);
    strcpy(ngname,what);
    growstr(&ngdir,&ngdlen,len);
    strcpy(ngdir,getngdir(ngname));
}

static char *myngdir;
static int ngdirlen = 0;

char *
getngdir(ngnam)
char *ngnam;
{
    register char *s;

    growstr(&myngdir,&ngdirlen,strlen(ngnam)+1);
    strcpy(myngdir,ngnam);
    for (s = myngdir; *s; s++)
	if (*s == '.')
	    *s = '/';
    return myngdir;
}
!STUFFY!FUNK!
echo Extracting NEW
cat >NEW <<'!STUFFY!FUNK!'
		    NEW FEATURES OF RN 4.4.3
   o	Configure changes:  check for active.times (see new-group comments
	below), termios systems (see termios comments later on), and also
	ask if ORGANIZATION should be ignored.  This latter change allows
	systems that use the ORGANIZATION variable for their own purposes
	a chance to only use NEWSORG, thus allowing them to take advantage
	of the default if NEWSORG is undefined (without this, everyone who
	uses rn would _have_ to define NEWSORG to avoid the ORGANIZATION
	define).
   o	Pnews.SH: support ignoring of ORGANIZATION; echo --> $echo;
	cat --> $cat.
   o	Rnmail.SH: support ignoring of ORGANIZATION.
   o	Many files: I've change the parameters of any function trying to
	pass a character (including bool) into a type_int (e.g. char_int).
	This avoids errors for ANSI compilers that don't believe that the
	promoted argument type is valid (they try to pass a char as a char,
	without promoting it to an int, and complain about the old syntax).
   o	addng.c:  the new new-group-finding code is in here.  Optimized the
	writing/reading of newsgroup lists by using "w+" and rewinding the
	file.  If ACTIVE_TIMES is defined, the new function find_new_groups()
	uses the NEWGROUPS command (in NNTP) or the ACTIVE_TIMES file (in
	regular rn) to determine new groups.  If it's not defined, then the
	find_new_groups() function does the old method (using the code moved
	here from init.c).
   o	added the DEB_NNTP define to output some useful NNTP debugging info
	without having all information scroll by like it does with the NNTP
	clientlib's debugging turned on.
   o	I optimized a few of the sscanf's to use "%*d" to skip numbers
	that were being ignored, and removed the useless variables.
   o	art.c:  enhanced the Newsgroups-magic code to show the Newsgroups
	line if it doesn't match the current group.  I find this really
	useful for browsing through junk or seeing which articles have
	been redirected with C new's '=' directive.
   o	autosub.c:  reordered the include files to avoid a problem with
	ANSI compilers.
   o	bits.c:  fixed a bug in the instr() call in the !NORELAY section
	(the ", TRUE" was in the wrong place).
   o	common.h, etc:  if TERMIOS is defined, include termios.h and use
	some slightly different term functions.  Configure was smart enough
	to NOT set this for suns, and a few other systems that don't like it.
   o	common.h:  if __STDC__ is defined, turn on the ANSI() prototypes
	automatically.
   o	common.h:  nullstr[] = ""; actually generates a warning(!) on some
	weird compilers -- changed to nullstr[1] = "";.
   o	common.h:  "Can't recreate..." message is used in the .newnewsrc
	writing code.
   o	config.h.SH:  conditionalize the including of the config.sh file
	like the other .SH files do.  Also added the new Configure stuff.
   o	config.h.SH needs to have its RCS comment character changed to "# ".
   o	config.h.SH:  all the changes in the tail end are tab/space changes
	that force the code to look pretty in config.h no matter if it is
	preceded by a "#define" or a "/*#undef".
   o	final.c:  int_catcher() needs an int parameter to agree with ANSI
	compilers.  sig_catcher() had an assumed int parameter warning.
   o	init.c:  more new-group changes (i.e. it calls find_new_groups(),
	and the old new-group code was moved to addng.c).
   o	intrp.c:  changes to support ignoring ORGANIZATION.  A slight tweak
	allows the organization file not not end in a newline.
   o	intrp.c:  moved the tmpbuf[] into the #ifdefs where it is used (to
	avoid an "unused" warning.  In the process, discovered a bug in the
	non-BSD code that tries to copy an uninitialized (now undefined) tmpbuf
	into buf (when it should be copying 's').
   o	last.c:  extended the contents of .rnlast to support the new-group
	code.  Handles reading the old .rnlast style gracefully.
   o	ng.c:  reset the value of extractdest and extractprog when entering
	a newsgroup.  This allows someone to set SAVEDIR to a roving value
	(like %c) and have an 'e' in group1 not affect an 'e' in group2.
	Within the group, each 'e' command will repeat the last destination
	and program if no parameters are used.
   o	ng.c:  note the values returned by the GROUP command in rrn so that
	we can add new articles that came in since our last fetch of the
	active file.  I've upgraded the ngmax[] array to non-debug status,
	and now use it to keep the group's maximum value (like abs1st[]
	does for the minimum).  This allows getngsize() to return a value
	higher than what is contained in the active file copy, and also
	to fetch a new copy of the active file if enough time has elapsed
	since our last fetch.
   o	ng.c:  fixed forcelast to get cleared before processing a command,
	and to get set on '-' just in case it goes to the end of the group.
   o	ng.c:  fixed some indent problems.
   o	ngdata.c:  added the lastactfetch variable (rrn) to keep track of
	when the active file copy was last fetched.
   o	ngdata.c:  getngsize() uses the value in ngmax[] to override the
	high active-file-copy value.  If ngmax[] is bigger and enough time
	has gone by, a new copy of the active file is fetched.
   o	ngdata.c:  more indent tweaks.
   o	ngdata.c:  fixed a1st to be a long (it might have been int or long,
	and sscanf() was expecting an int), and added "last" to sscanf the
	high newsgroup value at the same time abs1st is being set.  Fixed
	a problem with the sscanf being executed if the NNTP command failed.
   o	ngdata.c:  minor tweak to the "notdef" comment to make it accurate.
   o	ngdata.h:  MINFETCHTIME is set for 5 minutes before another active
	fetch is allowed.
   o	rcln.c:  minor optimization to remove tmpp; removed #ifdef DEBUGGING
	around the ngmax[] array; put \n's before the bogus newsgroup
	warnings.
   o	Allow some slack in the "newsgroup was reset" check to allow for the
	interaction of the ngmax[] array setting a high value in .newsrc
	that a cached version of the active file doesn't reflect yet (can
	happen when starting up rn in some rare cases).
   o	rcstuff.c:  broke out the code that parses the newsrc line into the
	function parse_rcline().  This allows the addition of a new function,
	abandon_ng() that restores the startup values for the current group
	from the .oldnewsrc file (bound to the 'A' command at the newsgroup
	level).
   o	rcstuff.c:  made addnewbydefault a global variable so that it could
	be reset by the 'a' command.  Without this, typing 'N' during the
	startup code would render the 'a' command useless, since all the
	groups you might want to add get an immediate 'n'o answer.
   o	rcstuff.c:  the "if (mode == 'i')" check is needed to keep the
	new-newsgroup-finding code sane.
   o	rcstuff.c:  I changed the code to add groups with a space after
	the ":" or "!".  It's not really required, but it avoids having the
	construct "group!187,193" show up in your .newsrc file when cross-
	posted articles are marked as read for unsubscribed groups.
   o	rcstuff.c:  the .newnewsrc-writing code uses the "cantrecreate"
	message from common.h, and the comments and indentation are fixed,
	as well as one extra ferror() check added.
   o	rcstuff.c:  the newsrc-array-growing code now zeros the ngnum array.
   o	respond.c: moved a negation used with strlen() to avoid problems if
	strlen() is declared to be unsigned.
   o    respond.c: changed the behavior of the 'f' command to ask the
	user if it is an unrelated topic.
   o	rn.c:  added the "direction" flag that makes the 'p' and 'P' command
	work in all circumstances.  Without this, if you have a restriction
	enabled and an empty non-matching group in the way, it won't backup
	at all (and might even go forward!).
   o	rn.c:  your change for outputting the prompt later in the game allows
	for the removal of the reprompt_newsgroup label with the moving of
	the dfltcmd initialization also.
   o	rn.c:  when rrn visits the end of the newsgroups prompt, it will
	fetch a new copy of the active file if enough time has elapsed.
   o	rn.c:  changed the "not found" prompt to mention the 'a' command
	(which is much more useful than 'g' alone).  Made 'g's error
	message a little more clear too.
   o	rn.c:  more indentation twiddles.
   o	rn.c:  removed the check for ' ' from the catchup code, because it's
	getting changed into the default command by setdef().
   o	rn.c:  added the 'A' command to abandon the current newsgroup's
	changes back to the startup state (which is contained in .oldnewsrc).
   o	rn.c:  have the 'a' command reset addnewbydefault to 0.
   o	term.c:  renamed ospeed "outspeed" so that it doesn't conflict with
	some weird system's polution of the name space.
   o	term.c:  support for the termios systems added.
   o	term.c:  winch_catcher() needed an int parameter for ANSI systems.
   o	util.c:  reorganized a couple returns to avoid warnings about not
	returning a value in a function.
   o	Configure now knows about DG Avion.

		    NEW FEATURES OF RN 4.4.2 vs RN 4.4
New % interpolation
	%E		the last directory to which extracted files were
			placed.

Configure improvements
	Configure knows about AIX and can build a version of rn that works
	correctly on AIX.
	Configure is generally smarter about getting symbols out of various
	type of archive files.
	The server.h include file is now generated outside of Configure via
	server.h.SH shell script.

General improvements
	rn no longer incorrectly interprets a . in a header line as a meta-
	character.
	The memory management in the newrc array managment code is now much
	better.

		    NEW FEATURES OF RN 4.4 vs RN 4.3

New or modified commands
	e		extract a shar or uuencoded file. (article level)
	g number	g command will go to a newsgroup by number where the
			the number corresponds to that used in the list 
			supplied by the 'L' command. (newsgroup level)
	z		supersede an article (article level)

New magic (use +H to turn them off)
	-Hfrom		displays only the commented portion of the user name.

New environment variables
	AUTOSUBSCRIBE	newsgroup pattern for groups to automatically
			subscribe to when found. Groups not matching
			are presented to the user via the usual
			subscription prompts.
	AUTOUNSUBSCRIBE newsgroup pattern for groups to not subscribe to.
			Groups matching this pattern are not subsribed to.
	EXSAVER		shell command that starts an extraction.
	UNSHAR		the unshar program to use (default /bin/sh).
	REPLYTO		the value to use for the "Reply-To:" header, if
			needed.
	NEWSORG		Same as ORGANIZATION. Used for those sites that
			need ORGANIZATION for other purposes (Apollos).
	SUPERSEDEHEADER The header format to use for a 'z' command.
New % interpolations
	%#		keeps an incremental count during a multi-file save,
			extract, etc.  ":s part.%#"
	%e		the last command executed to extract an article.

Configure improvements
	Now uses nm to read contents of libc. ar is used if nm fails.
	Configure also provides the option of editing config.sh before
	config.h and all the shell scripts are created.
	Configure stores the origanization name in double quotes in
	config.sh. This avoids a problem with organization names that
	have single quotes in them (i.e. many French and Canadian 
	organizations).
	Configure now knows about RISC/os, Stardents and uts environments.

General improvements
	Makes use of POSIX capabilities if present.
	ANSI C Compatible
	Hostname may be read in from a file instead of using system calls.
	ClariNet news headers are now recognized by rn. All header operations
	can be done on those headers.
	rn will dynamically allocate its structures to cope with any number
	of newsgroups in .newsrc or the active file.
	MMDF is now officially supported as a mail transfer agent.
	
Miscellaneous
	When GETPWENT it defined and an invalid userid is used, an 
	error message is returned. Previously, rn would core dump.

	The newsgroups script now knows how to deal with "bogus" newsgroups.
	[These are groups in the active files marked with status 'x'.]
	
	If there is no news on rn startup and the user enters a "g" at
	the newsgroup level, the program will now correctly note that
	no newsgroup name has been entered and reprompt.

	Hostnames are now checked without respect to upper/lower case.
	This fixes a problem with the cancel command (academ.COM != academ.com
	before the fix).

	The NEWSADMIN code was buggy and often didn't work correctly.
	This has been fixed.

	%P is used to find a place for rrn to create active and article
	files. Previously, /tmp was hardcoded in most places.

	newsgroups would not remove the active file copy it made when 
	used via NNTP. Now it does remove this copy when it exits.

	Corrected some null pointer problems in the search code. Specifically,
	entering entering / or ? when there was no previous search pattern
	would cause a core dump. Now, it tells the user there there is
	no previous pattern.

	rrn now exits and leaves the terminal in a usable state when a
	server timeout occurs.

	rrn now supports the longest lines allowed by the NNTP RFC.
	
	rn will try to preseve permissions on .newsrc when it recreates
	it. Previously, it didn't do this.

	rn deals with NFS timeouts better. If the active file (on an NFS
	mounted partition) goes away, rn shuts down gracefully now.

	

!STUFFY!FUNK!
echo Extracting rcln.c
cat >rcln.c <<'!STUFFY!FUNK!'
/* $Id: rcln.c,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
 *
 * $Log: rcln.c,v $
 * Revision 4.4.3.1  1992/02/01  03:09:32  sob
 * Release 4.4 Patchlevel 3
 *
 * Revision 4.4.2.1  1991/12/01  18:05:42  sob
 * Patchlevel 2 changes
 *
 * Revision 4.4.1.1  1991/09/25  19:38:08  sob
 * Some adaptions for CNEWS
 *
 * Revision 4.4  1991/09/09  20:27:37  sob
 * release 4.4
 *
 *
 * 
 */
/* This software is Copyright 1991 by Stan Barber. 
 *
 * Permission is hereby granted to copy, reproduce, redistribute or otherwise
 * use this software as long as: there is no monetary profit gained
 * specifically from the use or reproduction of this software, it is not
 * sold, rented, traded or otherwise marketed, and this copyright notice is
 * included prominently in any copy made. 
 *
 * The author make no claims as to the fitness or correctness of this software
 * for any use whatsoever, and it is provided as is. Any use of this software
 * is at the user's own risk. 
 */

#include "EXTERN.h"
#include "common.h"
#include "util.h"
#include "rcstuff.h"
#include "ngdata.h"
#include "INTERN.h"
#include "rcln.h"

void
rcln_init()
{
    ;
}

#ifdef CATCHUP
void
catch_up(ngx)
NG_NUM ngx;
{
    char tmpbuf[128];
    
#ifdef VERBOSE
    IF(verbose)
	printf("\nMarking %s as all read.\n",rcline[ngx]) FLUSH;
    ELSE
#endif
#ifdef TERSE
	fputs("\nMarked read\n",stdout) FLUSH;
#endif
    sprintf(tmpbuf,"%s: 1-%ld", rcline[ngx],(long)getngsize(ngx));
    free(rcline[ngx]);
    rcline[ngx] = savestr(tmpbuf);
    *(rcline[ngx] + rcnums[ngx] - 1) = '\0';
    toread[ngx] = TR_NONE;
    write_rc();
}
#endif

/* add an article number to a newsgroup, if it isn't already read */

int
addartnum(artnum,ngnam)
ART_NUM artnum;
char *ngnam;
{
    register NG_NUM ngnum = find_ng(ngnam);
    register char *s, *t, *maxt = Nullch;
    ART_NUM min = 0, max = -1, lastnum = 0;
    char *mbuf;
    bool morenum;

    if (!artnum)
	return 0;
    if (ngnum == nextrcline || !rcnums[ngnum])
					/* not found in newsrc? */
	return 0;
#ifdef CACHEFIRST
    if (!abs1st[ngnum])
#else
    if (!toread[ngnum])
#endif
#if !defined(SERVER) || defined(MININACT)
					/* now is a good time to trim down */
	set_toread(ngnum);		/* the list due to expires if we */
					/* have not yet. */
#endif
#ifdef DEBUGGING
    if (artnum > ngmax[ngnum] + 100	/* allow for incoming articles */
       ) {
	printf("\nCorrupt Xref line!!!  %ld --> %s(1..%ld)\n",
	    artnum,ngnam,
	    ngmax[ngnum]) FLUSH;
	paranoid = TRUE;		/* paranoia reigns supreme */
	return -1;			/* hope this was the first newsgroup */
    }
#endif

    if (toread[ngnum] == TR_BOGUS)
	return 0;
#ifdef DEBUGGING
    if (debug & DEB_XREF_MARKER) {
	printf("%ld->\n%s%c%s\n",(long)artnum,rcline[ngnum],rcchar[ngnum],
	  rcline[ngnum] + rcnums[ngnum]) FLUSH;
    }
#endif
    s = rcline[ngnum] + rcnums[ngnum];
    while (*s == ' ') s++;		/* skip spaces */
    t = s;
    while (isdigit(*s) && artnum >= (min = atol(s))) {
					/* while it might have been read */
	for (t = s; isdigit(*t); t++) ;	/* skip number */
	if (*t == '-') {		/* is it a range? */
	    t++;			/* skip to next number */
	    if (artnum <= (max = atol(t)))
		return 0;		/* it is in range => already read */
	    lastnum = max;		/* remember it */
	    maxt = t;			/* remember position in case we */
					/* want to overwrite the max */
	    while (isdigit(*t)) t++;	/* skip second number */
	}
	else {
	    if (artnum == min)		/* explicitly a read article? */
		return 0;
	    lastnum = min;		/* remember what the number was */
	    maxt = Nullch;		/* last one was not a range */
	}
	while (*t && !isdigit(*t)) t++;	/* skip comma and any spaces */
	s = t;
    }
    
    /* we have not read it, so insert the article number before s */
    
    morenum = isdigit(*s);		/* will it need a comma after? */
    *(rcline[ngnum] + rcnums[ngnum] - 1) = rcchar[ngnum];
    mbuf = safemalloc((MEM_SIZE)(strlen(s) + (s-rcline[ngnum]) + 8));
    strcpy(mbuf,rcline[ngnum]);		/* make new rc line */
    if (maxt && lastnum && artnum == lastnum+1)
    					/* can we just extend last range? */
	t = mbuf + (maxt-rcline[ngnum]);/* then overwrite previous max */
    else {
	t = mbuf + (t-rcline[ngnum]);	/* point t into new line instead */
	if (lastnum) {			/* have we parsed any line? */
	    if (!morenum)		/* are we adding to the tail? */
		*t++ = ',';		/* supply comma before */
	    if (!maxt && artnum == lastnum+1 && *(t-1) == ',')
					/* adjacent singletons? */
		*(t-1) = '-';		/* turn them into a range */
	}
    }
    if (morenum) {			/* is there more to life? */
	if (min == artnum+1) {		/* can we consolidate further? */
	    bool range_before = (*(t-1) == '-');
	    bool range_after;
	    char *nextmax;

	    for (nextmax = s; isdigit(*nextmax); nextmax++) ;
	    range_after = *nextmax++ == '-';
	    
	    if (range_before)
		*t = '\0';		/* artnum is redundant */
	    else
		sprintf(t,"%ld-",(long)artnum);/* artnum will be new min */
	    
	    if (range_after)
		s = nextmax;		/* *s is redundant */
	/*  else
		s = s */		/* *s is new max */
	}
	else
	    sprintf(t,"%ld,",(long)artnum);	/* put the number and comma */
    }
    else
	sprintf(t,"%ld",(long)artnum);	/* put the number there (wherever) */
    strcat(t,s);			/* copy remainder of line */
#ifdef DEBUGGING
    if (debug & DEB_XREF_MARKER) {
	printf("%s\n",mbuf) FLUSH;
    }
#endif
    free(rcline[ngnum]);
    rcline[ngnum] = mbuf;		/* pull the switcheroo */
    *(rcline[ngnum] + rcnums[ngnum] - 1) = '\0';
					/* wipe out : or ! */
    if (toread[ngnum] > TR_NONE)	/* lest we turn unsub into bogus */
	--toread[ngnum];
    return 0;
}

#ifdef MCHASE
/* delete an article number from a newsgroup, if it is there */

void
subartnum(artnum,ngnam)
register ART_NUM artnum;
char *ngnam;
{
    register NG_NUM ngnum = find_ng(ngnam);
    register char *s, *t;
    register ART_NUM min, max;
    char *mbuf;
    int curlen;

    if (!artnum)
	return;
    if (ngnum == nextrcline || !rcnums[ngnum])
	return;				/* not found in newsrc? */
#ifdef DEBUGGING
    if (debug & DEB_XREF_MARKER) {
	printf("%ld<-\n%s%c%s\n",(long)artnum,rcline[ngnum],rcchar[ngnum],
	  rcline[ngnum] + rcnums[ngnum]) FLUSH;
    }
#endif
    s = rcline[ngnum] + rcnums[ngnum];
    while (*s == ' ') s++;		/* skip spaces */
    
    /* a little optimization, since it is almost always the last number */
    
    for (t=s; *t; t++) ;		/* find end of string */
    curlen = t-rcline[ngnum];
    for (t--; isdigit(*t); t--) ;	/* find previous delim */
    if (*t == ',' && atol(t+1) == artnum) {
	*t = '\0';
	if (toread[ngnum] >= TR_NONE)
	    ++toread[ngnum];
#ifdef DEBUGGING
	if (debug & DEB_XREF_MARKER)
	    printf("%s%c %s\n",rcline[ngnum],rcchar[ngnum],s) FLUSH;
#endif
	return;
    }

    /* not the last number, oh well, we may need the length anyway */

    while (isdigit(*s) && artnum >= (min = atol(s))) {
					/* while it might have been read */
	for (t = s; isdigit(*t); t++) ;	/* skip number */
	if (*t == '-') {		/* is it a range? */
	    t++;			/* skip to next number */
	    max = atol(t);
	    while (isdigit(*t)) t++;	/* skip second number */
	    if (artnum <= max) {
					/* it is in range => already read */
		if (artnum == min) {
		    min++;
		    artnum = 0;
		}
		else if (artnum == max) {
		    max--;
		    artnum = 0;
		}
		*(rcline[ngnum] + rcnums[ngnum] - 1) = rcchar[ngnum];
		mbuf = safemalloc((MEM_SIZE)(curlen + (artnum?15:2)));
		*s = '\0';
		strcpy(mbuf,rcline[ngnum]);	/* make new rc line */
		s = mbuf + (s-rcline[ngnum]);
					/* point s into mbuf now */
		if (artnum) {		/* split into two ranges? */
		    prange(s,min,artnum-1);
		    s += strlen(s);
		    *s++ = ',';
		    prange(s,artnum+1,max);
		}
		else			/* only one range */
		    prange(s,min,max);
		s += strlen(s);
		strcpy(s,t);		/* copy remainder over */
#ifdef DEBUGGING
		if (debug & DEB_XREF_MARKER) {
		    printf("%s\n",mbuf) FLUSH;
		}
#endif
		free(rcline[ngnum]);
		rcline[ngnum] = mbuf;	/* pull the switcheroo */
		*(rcline[ngnum] + rcnums[ngnum] - 1) = '\0';
					/* wipe out : or ! */
		if (toread[ngnum] >= TR_NONE)
		    ++toread[ngnum];
		return;
	    }
	}
	else {
	    if (artnum == min) {	/* explicitly a read article? */
		if (*t == ',')		/* pick a comma, any comma */
		    t++;
		else if (s[-1] == ',')
		    s--;
		else if (s[-2] == ',')	/* (in case of space) */
		    s -= 2;
		strcpy(s,t);		/* no need to realloc */
		if (toread[ngnum] >= TR_NONE)
		    ++toread[ngnum];
#ifdef DEBUGGING
		if (debug & DEB_XREF_MARKER) {
		    printf("%s%c%s\n",rcline[ngnum],rcchar[ngnum],
		      rcline[ngnum] + rcnums[ngnum]) FLUSH;
		}
#endif
		return;
	    }
	}
	while (*t && !isdigit(*t)) t++;	/* skip comma and any spaces */
	s = t;
    }
}

void
prange(where,min,max)
char *where;
ART_NUM min,max;
{
    if (min == max)
	sprintf(where,"%ld",(long)min);
    else
	sprintf(where,"%ld-%ld",(long)min,(long)max);
}
#endif

/* calculate the number of unread articles for a newsgroup */

void
set_toread(ngnum)
register NG_NUM ngnum;
{
    register char *s, *c, *h;
    char tmpbuf[64], *mybuf = tmpbuf;
    char *nums;
    int length;
#ifdef CACHEFIRST
    bool virgin_ng = (!abs1st[ngnum]);
#endif
    ART_NUM ngsize = getngsize(ngnum);
    ART_NUM unread = ngsize;
    ART_NUM newmax;

    ngmax[ngnum] = ngsize;		/* for checking out-of-range Xrefs */
    if (ngsize == TR_BOGUS) {
	printf("\nWarning!  Bogus newsgroup: %s\n",rcline[ngnum]) FLUSH;
	paranoid = TRUE;
	toread[ngnum] = TR_BOGUS;
	return;
    }
#ifdef CACHEFIRST
    if (virgin_ng)
#else
    if (!toread[ngnum])
#endif
    {
	sprintf(tmpbuf," 1-%ld",(long)ngsize);
	if (strNE(tmpbuf,rcline[ngnum]+rcnums[ngnum]))
	    checkexpired(ngnum,ngsize);	/* this might realloc rcline */
    }
    nums = rcline[ngnum]+rcnums[ngnum];
    length = strlen(nums);
    if (length >= 60)
	mybuf = safemalloc((MEM_SIZE)(length+5));
    strcpy(mybuf,nums);
    mybuf[length++] = ',';
    mybuf[length] = '\0';
    for (s = mybuf; isspace(*s); s++)
	    ;
    for ( ; (c = index(s,',')) != Nullch ; s = ++c) {
				    /* for each range */
	*c = '\0';			/* keep index from running off */
	if ((h = index(s,'-')) != Nullch)	/* find - in range, if any */
	    unread -= (newmax = atol(h+1)) - atol(s) + 1;
	else if (newmax = atol(s))
	    unread--;		/* recalculate length */
	if (newmax > ngsize) {	/* paranoia check */
	    if (newmax > ngsize + 100) {
		unread = -1;
		break;
	    } else {
		unread += newmax - ngsize;
		ngmax[ngnum] = ngsize = newmax;
	    }
	}
    }
    if (unread >= 0)		/* reasonable number? */
	toread[ngnum] = (ART_UNREAD)unread;
					/* remember how many are left */
    else {				/* SOMEONE RESET THE NEWSGROUP!!! */
	toread[ngnum] = (ART_UNREAD)ngsize;
					/* assume nothing carried over */
	printf("\nWarning!  Somebody reset %s--assuming nothing read.\n",
	    rcline[ngnum]) FLUSH;
	*(rcline[ngnum] + rcnums[ngnum]) = '\0';
	paranoid = TRUE;		/* enough to make a guy paranoid */
    }
    if (mybuf != tmpbuf)
	free(mybuf);
    if (rcchar[ngnum] == NEGCHAR)
	toread[ngnum] = TR_UNSUB;
}

/* make sure expired articles are marked as read */

void
checkexpired(ngnum,ngsize)
register NG_NUM ngnum;
ART_NUM ngsize;
{
    register ART_NUM a1st = getabsfirst(ngnum,ngsize);
    register char *s, *t;
    register ART_NUM num, lastnum = 0;
    char *mbuf, *newnum;

    if (a1st<=1)
	return;
#ifdef DEBUGGING
    if (debug & DEB_XREF_MARKER) {
	printf("1-%ld->\n%s%c%s\n",(long)(a1st-1),rcline[ngnum],rcchar[ngnum],
	  rcline[ngnum] + rcnums[ngnum]) FLUSH;
    }
#endif
    for (s = rcline[ngnum] + rcnums[ngnum]; isspace(*s); s++);
    while (*s && (num = atol(s)) <= a1st) {
	while (isdigit(*s)) s++;
	while (*s && !isdigit(*s)) s++;
	lastnum = num;
    }
    if (*s) {
	if (s[-1] == '-') {			/* landed in a range? */
	    if (lastnum != 1) {
		if (3 + strlen(s) > strlen(rcline[ngnum]+rcnums[ngnum])) {
		    mbuf = safemalloc((MEM_SIZE)(rcnums[ngnum] + 3 +
			strlen(s) + 1));
		    strcpy(mbuf, rcline[ngnum]);
		    sprintf(mbuf+rcnums[ngnum]," 1-%s",s);
		    free(rcline[ngnum]);
		    rcline[ngnum] = mbuf;
		} else {
		    sprintf(rcline[ngnum]+rcnums[ngnum]," 1-%s",s);
		}
	    }
	    goto ret;
	}
    }
    /* s now points to what should follow first range */
    if (s - rcline[ngnum] > rcnums[ngnum] + 10) 
	mbuf = rcline[ngnum];
    else {
	mbuf = safemalloc((MEM_SIZE)(rcnums[ngnum] + strlen(s) + 10));
	strcpy(mbuf,rcline[ngnum]);
    }
    newnum = t = mbuf+rcnums[ngnum];
    sprintf(t," 1-%ld",(long)(a1st - (lastnum != a1st)));
    if (*s) {
	t += strlen(t);
	*t++ = ',';
	strcpy(t,s);
    }
    if (!checkflag && mbuf == rcline[ngnum]) {
	rcline[ngnum] = saferealloc(rcline[ngnum],
	    (MEM_SIZE)(rcnums[ngnum] + strlen(newnum) + 1));
    }
    else {
	if (!checkflag)
	    free(rcline[ngnum]);
	rcline[ngnum] = mbuf;
    }

ret:;		/* semicolon in case DEBUGGING undefined */
#ifdef DEBUGGING
    if (debug & DEB_XREF_MARKER) {
	printf("%s%c%s\n",rcline[ngnum],rcchar[ngnum],
	  rcline[ngnum] + rcnums[ngnum]) FLUSH;
    }
#endif
}

!STUFFY!FUNK!
echo Extracting sw.c
cat >sw.c <<'!STUFFY!FUNK!'
/* $Id: sw.c,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
 *
 * $Log: sw.c,v $
 * Revision 4.4.3.1  1992/02/01  03:09:32  sob
 * Release 4.4 Patchlevel 3
 *
 * Revision 4.4  1991/09/09  20:27:37  sob
 * release 4.4
 *
 *
 * 
 */
/* This software is Copyright 1991 by Stan Barber. 
 *
 * Permission is hereby granted to copy, reproduce, redistribute or otherwise
 * use this software as long as: there is no monetary profit gained
 * specifically from the use or reproduction of this software, it is not
 * sold, rented, traded or otherwise marketed, and this copyright notice is
 * included prominently in any copy made. 
 *
 * The author make no claims as to the fitness or correctness of this software
 * for any use whatsoever, and it is provided as is. Any use of this software
 * is at the user's own risk. 
 */

#include "EXTERN.h"
#include "common.h"
#include "util.h"
#include "head.h"
#include "only.h"
#include "term.h"
#include "ng.h"
#include "intrp.h"
#include "INTERN.h"
#include "sw.h"

void
sw_init(argc,argv,tcbufptr)
int argc;
char *argv[];
char **tcbufptr;
{
    register int i;

    if (argc >= 2 && strEQ(argv[1],"-c"))
	checkflag=TRUE;			/* so we can optimize for -c */
    interp(*tcbufptr,1024,GLOBINIT);
    sw_file(tcbufptr,FALSE);
    safecpy(*tcbufptr,getenv("RNINIT"),1024);
    if (**tcbufptr) {
	if (**tcbufptr == '/') {
	    sw_file(tcbufptr,TRUE);
	}
	else
	    sw_list(*tcbufptr);
    }

    for (i = 1; i < argc; i++)
	decode_switch(argv[i]);
}

void
sw_file(tcbufptr,bleat)
char **tcbufptr;
bool_int bleat;
{
    int initfd = open(*tcbufptr,0);
	
    if (initfd >= 0) {
	fstat(initfd,&filestat);
	if (filestat.st_size > 1024)
	    *tcbufptr = saferealloc(*tcbufptr,(MEM_SIZE)filestat.st_size);
	if (filestat.st_size) {
	    read(initfd,*tcbufptr,(int)filestat.st_size);
	    (*tcbufptr)[filestat.st_size-1] = '\0';
				/* wipe out last newline */
	    sw_list(*tcbufptr);
	}
	else
	    **tcbufptr = '\0';
	close(initfd);
    }
    else {
	if (bleat)
	    printf(cantopen,*tcbufptr) FLUSH;
	**tcbufptr = '\0';
    }
}

/* decode a list of space separated switches */

void
sw_list(swlist)
char *swlist;
{
    char *tmplist = safemalloc((MEM_SIZE) strlen(swlist) + 2);
					/* semi-automatic string */
    register char *p, inquote = 0;

    strcpy(tmplist,swlist);
    for (p=tmplist; isspace(*p); p++) ;	/* skip any initial spaces */
    while (*p) {			/* "String, or nothing" */
	if (!inquote && isspace(*p)) {	/* word delimiter? */
	    *p++ = '\0';		/* chop here */
	    while (isspace(*p))		/* these will be ignored later */
		p++;
	}
	else if (inquote == *p) {
	    strcpy(p,p+1);		/* delete trailing quote */
	    inquote = 0;		/* no longer quoting */
	}
	else if (!inquote && *p == '"' || *p == '\'') {
					/* OK, I know when I am not wanted */
	    inquote = *p;		/* remember single or double */
	    strcpy(p,p+1);		/* delete the quote */
	}				/* (crude, but effective) */
	else if (*p == '\\') {		/* quoted something? */
	    if (p[1] == '\n')		/* newline? */
		strcpy(p,p+2);		/* "I didn't see anything" */
	    else {
		strcpy(p,p+1);		/* delete the backwhack */
		p++;			/* leave the whatever alone */
	    }
	}
	else
	    p++;			/* normal char, leave it alone */
    }
    *++p = '\0';			/* put an extra null on the end */
    if (inquote)
	printf("Unmatched %c in switch\n",inquote) FLUSH;
    for (p = tmplist; *p; /* p += strlen(p)+1 */ ) {
	decode_switch(p);
	while (*p++) ;			/* point at null + 1 */
    }
    free(tmplist);			/* this oughta be in Ada */
}

/* decode a single switch */

void
decode_switch(s)
register char *s;
{
    while (isspace(*s))			/* ignore leading spaces */
	s++;
#ifdef DEBUGGING
    if (debug)
	printf("Switch: %s\n",s) FLUSH;
#endif
    if (*s != '-' && *s != '+') {	/* newsgroup pattern */
	setngtodo(s);
    }
    else {				/* normal switch */
	bool upordown = *s == '-' ? TRUE : FALSE;
	char tmpbuf[LBUFLEN];

	s++;
	switch (*s) {
#ifdef TERMMOD
	case '=': {
	    char *beg = s+1;

	    while (*s && *s != '-' && *s != '+') s++;
	    cpytill(tmpbuf,beg,*s);
	    if (upordown ? strEQ(getenv("TERM"),tmpbuf)
	    		 : strNE(getenv("TERM"),tmpbuf) ) {
		decode_switch(s);
	    }
	    break;
	}
#endif
#ifdef BAUDMOD
	case '0': case '1': case '2': case '3': case '4':
	case '5': case '6': case '7': case '8': case '9':
	    if (upordown ? (just_a_sec*10 <= atoi(s))
	    		 : (just_a_sec*10 >= atoi(s)) ) {
		while (isdigit(*s)) s++;
		decode_switch(s);
	    }
	    break;
#endif
	case '/':
	    if (checkflag)
		break;
#ifdef SETENV
	    setenv("SAVEDIR",  upordown ? "%p/%c" : "%p" );
	    setenv("SAVENAME", upordown ? "%a"    : "%^C");
#else
	    notincl("-/");
#endif
	    break;
	case 'c':
	    checkflag = upordown;
	    break;
	case 'C':
	    s++;
	    if (*s == '=') s++;
	    docheckwhen = atoi(s);
	    break;
	case 'd': {
	    if (checkflag)
		break;
	    s++;
	    if (*s == '=') s++;
	    if (cwd) {
		chdir(cwd);
		free(cwd);
	    }
	    cwd = savestr(s);
	    break;
	}
#ifdef DEBUGGING
	case 'D':
	    s++;
	    if (*s == '=') s++;
	    if (*s)
		if (upordown)
		    debug |= atoi(s);
		else
		    debug &= ~atoi(s);
	    else
		if (upordown)
		    debug |= 1;
		else
		    debug = 0;
	    break;
#endif
	case 'e':
	    erase_screen = upordown;
	    break;
	case 'E':
#ifdef SETENV
	    s++;
	    if (*s == '=')
		s++;
	    strcpy(tmpbuf,s);
	    s = index(tmpbuf,'=');
	    if (s) {
		*s++ = '\0';
		setenv(tmpbuf,s);
	    }
	    else
		setenv(tmpbuf,nullstr);
#else
	    notincl("-E");
#endif
	    break;
	case 'F':
	    s++;
	    indstr = savestr(s);
	    break;
#ifdef INNERSEARCH
	case 'g':
	    gline = atoi(s+1)-1;
	    break;
#endif
	case 'H':
	case 'h': {
	    register int len, i;
	    char *t;
	    int flag = (*s == 'h' ? HT_HIDE : HT_MAGIC);
	    
	    if (checkflag)
		break;
	    s++;
	    len = strlen(s);
	    for (t=s; *t; t++)
		if (isupper(*t))
		   *t = tolower(*t);
	    for (i=HEAD_FIRST; i<HEAD_LAST; i++)
		if (!len || strnEQ(s,htype[i].ht_name,len))
		    if (upordown)
			htype[i].ht_flags |= flag;
		    else
			htype[i].ht_flags &= ~flag;
	    break;
	}
	case 'i':
	    s++;
	    if (*s == '=') s++;
	    initlines = atoi(s);
	    initlines_specified = TRUE;
	    break;
	case 'l':
	    muck_up_clear = upordown;
	    break;
	case 'L':
#ifdef CLEAREOL
	    can_home_clear = upordown;
#else
	    notincl("-L");
#endif
	    break;
	case 'M':
	    mbox_always = upordown;
	    break;
	case 'm':
	    s++;
	    if (*s == '=') s++;
	    if (!upordown)
		marking = NOMARKING;
	    else if (*s == 'u')
		marking = UNDERLINE;
	    else {
		marking = STANDOUT;
	    }
	    break;
	case 'N':
	    norm_always = upordown;
	    break;
#ifdef VERBOSE
	case 'n':
	    fputs("This isn't readnews.  Don't use -n.\n\n",stdout) FLUSH;
	    break;
#endif
	case 'r':
	    findlast = upordown;
	    break;
	case 's':
	    s++;
	    if (*s == '=') s++;
	    if (*s) {
		countdown = atoi(s);
		suppress_cn = FALSE;
	    }
	    else {
		if (!upordown)
		    countdown = 5;
		suppress_cn = upordown;
	    }
	    break;
	case 'S':
#ifdef ARTSEARCH
	    s++;
	    if (*s == '=') s++;
	    if (*s)
		scanon = atoi(s);
	    else
		scanon = upordown*3;
#else
	    notincl("-S");
#endif
	    break;
	case 't':
#ifdef VERBOSE
#ifdef TERSE
	    verbose = !upordown;
#else
	    notincl("+t");
#endif
#else
	    notincl("+t");
#endif
	    break;
	case 'T':
	    typeahead = upordown;
	    break;
	case 'v':
#ifdef VERIFY
	    verify = upordown;
#else
	    notincl("-v");
#endif
	    break;
	/*
	 * People want a way to avoid checking for new newsgroups on startup.
	 */
	case 'q':
		quickstart = upordown;
		break;
	default:
#ifdef VERBOSE
	    IF(verbose)
		printf("\nIgnoring unrecognized switch: -%c\n", *s) FLUSH;
	    ELSE
#endif
#ifdef TERSE
		printf("\nIgnoring -%c\n", *s) FLUSH;
#endif
	    break;
	}
    }
}

/* print current switch values */

void
pr_switches()
{
    static char mp[2] = {'+','-'};
    register int i;
    
    fputs("\nCurrent switch settings:\n",stdout);
    printf("%c/ ", mp[strEQ(getval("SAVEDIR",SAVEDIR),"%p/%c")]);
    printf("%cc ", mp[checkflag]);
    printf("-C%d ", docheckwhen);
    printf("-d%s ", cwd);
#ifdef DEBUGGING
    if (debug)
	printf("-D%d ", debug);
#endif
    printf("%ce ", mp[erase_screen]);
    printf("-F\"%s\" ", indstr);
#ifdef INNERSEARCH
    printf("-g%d", gline);
#endif
    putchar('\n');
#ifdef VERBOSE
    if (verbose) {
	for (i=HEAD_FIRST; i<HEAD_LAST; i++)
	    printf("%ch%s%c",
		mp[htype[i].ht_flags & HT_HIDE], htype[i].ht_name,
		(! (i % 5) ? '\n' : ' ') );
    }
#endif
    printf("-i%d ", initlines);
    printf("%cl ", mp[muck_up_clear]);
#ifdef CLEAREOL
    printf("%cL ", mp[can_home_clear]);
#endif /* CLEAREOL */
    if (marking)
	printf("-m%c ",marking==UNDERLINE?'u':'s');
    else
	printf("+m ");
    printf("%cM ", mp[mbox_always]);
    printf("%cN ", mp[norm_always]);
    printf("%cr ", mp[findlast]);
    if (countdown)
	printf("-s%d ", countdown);
    else
	printf("%cs ", mp[suppress_cn]);
#ifdef ARTSEARCH
    if (scanon)
	printf("-S%d ",scanon);
    else
	printf("+S ");
#endif
#ifdef VERBOSE
#ifdef TERSE
    printf("%ct ", mp[!verbose]);
#endif
#endif
    printf("%cT ", mp[typeahead]);
#ifdef VERIFY
    printf("%cv ", mp[verify]);
#endif
    fputs("\n\n",stdout) FLUSH;
#ifdef ONLY
    if (maxngtodo) {
#ifdef VERBOSE
	IF(verbose)
	    fputs("Current restriction:",stdout);
	ELSE
#endif
#ifdef TERSE
	    fputs("Only:",stdout);
#endif
	for (i=0; i<maxngtodo; i++)
	    printf(" %s",ngtodo[i]);
	fputs("\n\n",stdout) FLUSH;
    }
#ifdef VERBOSE
    else if (verbose)
	fputs("No restriction.\n\n",stdout) FLUSH;
#endif
#endif
}

void
cwd_check()
{
    char tmpbuf[LBUFLEN];

    if (!cwd)
	cwd = savestr(filexp("~/News"));
    strcpy(tmpbuf,cwd);
    if (chdir(cwd)) {
	safecpy(tmpbuf,filexp(cwd),sizeof tmpbuf);
	if (makedir(tmpbuf,MD_DIR) < 0 || chdir(tmpbuf) < 0) {
	    interp(cmd_buf, (sizeof cmd_buf), "%~/News");
	    if (makedir(cmd_buf,MD_DIR) < 0)
		strcpy(tmpbuf,homedir);
	    else
		strcpy(tmpbuf,cmd_buf);
	    chdir(tmpbuf);
#ifdef VERBOSE
	    IF(verbose)
		printf("\
Cannot make directory %s--\n\
	articles will be saved to %s\n\
\n\
",cwd,tmpbuf) FLUSH;
	    ELSE
#endif
#ifdef TERSE
		printf("\
Can't make %s--\n\
	using %s\n\
\n\
",cwd,tmpbuf) FLUSH;
#endif
	}
    }
    free(cwd);
    getwd(tmpbuf);
    if (eaccess(tmpbuf,2)) {
#ifdef VERBOSE
	IF(verbose)
	    printf("\
Current directory %s is not writeable--\n\
	articles will be saved to home directory\n\n\
",tmpbuf) FLUSH;
	ELSE
#endif
#ifdef TERSE
	    printf("%s not writeable--using ~\n\n",tmpbuf) FLUSH;
#endif
	strcpy(tmpbuf,homedir);
    }
    cwd = savestr(tmpbuf);
}
!STUFFY!FUNK!
echo Extracting term.h
cat >term.h <<'!STUFFY!FUNK!'
/* $Id: term.h,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
 *
 * $Log: term.h,v $
 * Revision 4.4.3.1  1992/02/01  03:09:32  sob
 * Release 4.4 Patchlevel 3
 *
 * Revision 4.4  1991/09/09  20:27:37  sob
 * release 4.4
 *
 *
 * 
 */
/* This software is Copyright 1991 by Stan Barber. 
 *
 * Permission is hereby granted to copy, reproduce, redistribute or otherwise
 * use this software as long as: there is no monetary profit gained
 * specifically from the use or reproduction of this software, it is not
 * sold, rented, traded or otherwise marketed, and this copyright notice is
 * included prominently in any copy made. 
 *
 * The author make no claims as to the fitness or correctness of this software
 * for any use whatsoever, and it is provided as is. Any use of this software
 * is at the user's own risk. 
 */

#ifdef PUSHBACK
EXT char circlebuf[PUSHSIZE];
EXT int nextin INIT(0);
EXT int nextout INIT(0);
#ifdef PENDING
#ifdef FIONREAD
EXT long iocount INIT(0);
#ifndef lint
#define input_pending() (nextin!=nextout || (ioctl(0, FIONREAD, &iocount),(int)iocount))
#else
#define input_pending() bizarre
#endif /* lint */
#else /* FIONREAD */
#ifdef RDCHK
#define input_pending() (rdchk(0) > 0)		/* boolean only */
#else /*  RDCHK */
int circfill();
EXT int devtty INIT(0);
#ifndef lint
#define input_pending() (nextin!=nextout || circfill())
#else
#define input_pending() bizarre
#endif /* lint */
#endif /* RDCHK */
#endif /* FIONREAD */
#else /* PENDING */
#ifndef lint
#define input_pending() (nextin!=nextout)
#else
#define input_pending() bizarre
#endif /* lint */
#endif /* PENDING */
#else /* PUSHBACK */
#ifdef PENDING
#ifdef FIONREAD	/* must have FIONREAD or O_NDELAY for input_pending() */
#define read_tty(addr,size) read(0,addr,size)
#ifndef lint
#define input_pending() (ioctl(0, FIONREAD, &iocount),(int)iocount)
#else
#define input_pending() bizarre
#endif /* lint */
EXT long iocount INIT(0);

#else /* FIONREAD */

#ifdef RDCHK
#define input_pending() (rdchk(0) > 0)		/* boolean only */
#else /*  RDCHK */

EXT int devtty INIT(0);
EXT bool is_input INIT(FALSE);
EXT char pending_ch INIT(0);
#ifndef lint
#define input_pending() (is_input || (is_input=read(devtty,&pending_ch,1)))
#else
#define input_pending() bizarre
#endif /* lint */
#endif /*  RDCHK */
#endif /* FIONREAD */
#else /* PENDING */
#define read_tty(addr,size) read(0,addr,size)
#define input_pending() (FALSE)
#endif /* PENDING */
#endif /* PUSHBACK */

/* stuff wanted by terminal mode diddling routines */

#ifdef TERMIO
EXT struct termio _tty, _oldtty;
#else
# ifdef TERMIOS
EXT struct termios _tty, _oldtty;
# else
EXT struct sgttyb _tty;
EXT int _res_flg INIT(0);
# endif
#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() (ioctl(_tty_ch, TCGETA, &_oldtty),ioctl(_tty_ch, TCGETA, &_tty))
#define	resetty() ((bizarre=0),ioctl(_tty_ch, TCSETAF, &_oldtty))
#define unflush_output()

#else /* !TERMIO */
# ifdef TERMIOS

#define crmode() ((bizarre=1), _tty.c_lflag &= ~ICANON,_tty.c_cc[VMIN]=1,tcsetattr(_tty_ch, TCSAFLUSH, &_tty))
#define nocrmode() ((bizarre=1),_tty.c_lflag |= ICANON,_tty.c_cc[VEOF] = CEOF,tcsetattr(_tty_ch, TCSAFLUSH,&_tty))
#define echo()	 ((bizarre=1),_tty.c_lflag |= ECHO, tcsetattr(_tty_ch, TCSAFLUSH, &_tty))
#define noecho() ((bizarre=1),_tty.c_lflag &=~ECHO, tcsetattr(_tty_ch, TCSAFLUSH, &_tty))
#define nl()	 ((bizarre=1),_tty.c_iflag |= ICRNL,_tty.c_oflag |= ONLCR,tcsetattr(_tty_ch, TCSAFLUSH, &_tty))
#define nonl()	 ((bizarre=1),_tty.c_iflag &=~ICRNL,_tty.c_oflag &=~ONLCR,tcsetattr(_tty_ch, TCSAFLUSH, &_tty))
#define	savetty() (tcgetattr(_tty_ch, &_oldtty),tcgetattr(_tty_ch, &_tty))
#define	resetty() ((bizarre=0),tcsetattr(_tty_ch, TCSAFLUSH, &_oldtty))
#define unflush_output()

# else /* !TERMIOS */

#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() (gtty(_tty_ch, &_tty), _res_flg = _tty.sg_flags)
#define	resetty() ((bizarre=0),_tty.sg_flags = _res_flg, stty(_tty_ch, &_tty))
#  ifdef LFLUSHO
#   ifndef lint
EXT int lflusho INIT(LFLUSHO);
#   else
EXT long lflusho INIT(LFLUSHO);
#   endif /* lint */
#define unflush_output() (ioctl(_tty_ch,TIOCLBIC,&lflusho))
#  else
#define unflush_output()
#  endif /* LFLUSHO */
# endif /* TERMIOS */

#endif /* TERMIO */

#ifdef TIOCSTI
#ifdef lint
#define forceme(c) ioctl(_tty_ch,TIOCSTI,Null(long*))	/* ghad! */
#else
#define forceme(c) ioctl(_tty_ch,TIOCSTI,c) /* pass character in " " */
#endif /* lint */
#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 int GT;				/* hardware tabs */
EXT char *BC INIT(Nullch);		/* backspace character */
EXT char *UP INIT(Nullch);		/* move cursor up one line */
EXT char *CR INIT(Nullch);		/* get to left margin, somehow */
EXT char *VB INIT(Nullch);		/* visible bell */
EXT char *CL INIT(Nullch);		/* home and clear screen */
EXT char *CE INIT(Nullch);		/* clear to end of line */
EXT char *TI INIT(Nullch);		/* initialize terminal */
EXT char *TE INIT(Nullch);		/* reset terminal */
#ifdef CLEAREOL
EXT char *CM INIT(Nullch);		/* cursor motion */
EXT char *HO INIT(Nullch);		/* home cursor */
EXT char *CD INIT(Nullch);		/* clear to end of display */
#endif /* CLEAREOL */
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() */

#ifdef _POSIX_SOURCE
EXT speed_t outspeed INIT(0);		/* terminal output speed, */
#else
EXT long outspeed INIT(0);		/* 	for use by tputs() */
#endif

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) FLUSH
#define clear() tputs(CL,LINES,putchr) FLUSH
#define erase_eol() tputs(CE,1,putchr) FLUSH
#ifdef CLEAREOL
#define clear_rest() tputs(CD,LINES,putchr) FLUSH
#define maybe_eol() if(erase_screen&&can_home_clear)tputs(CE,1,putchr) FLUSH
#endif /* CLEAREOL */
#define underline() tputs(US,1,putchr) FLUSH
#define un_underline() tputs(UE,1,putchr) FLUSH
#define underchar() tputs(UC,0,putchr) FLUSH
#define standout() tputs(SO,1,putchr) FLUSH
#define un_standout() tputs(SE,1,putchr) FLUSH
#define up_line() tputs(UP,1,putchr) FLUSH
#define carriage_return() tputs(CR,1,putchr) FLUSH
#define dingaling() tputs(VB,1,putchr) FLUSH
#else
  ????????		/* up to you */
#endif

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

void	term_init ANSI((void));
void	term_set ANSI((char *));
#ifdef PUSHBACK
void	pushchar ANSI((char_int));
void	mac_init ANSI((char *));
void	mac_line ANSI((char *,char *,int));
void	show_macros ANSI((void));
#endif
char	putchr ANSI((char_int));	/* routine for tputs to call */
bool	finish_command ANSI((int));
void	eat_typeahead ANSI((void));
void	settle_down ANSI((void));
#ifdef HAVETERMLIB
void	termlib_init ANSI((void));
void	termlib_reset ANSI((void));
#endif
#ifndef read_tty
    int		read_tty ANSI((char *,int));
#endif
void	underprint ANSI((char *));
#ifdef NOFIREWORKS
    void	no_sofire ANSI((void));
    void	no_ulfire ANSI((void));
#endif
void	getcmd ANSI((char *));
int	get_anything ANSI((void));
void	in_char ANSI((char *,char_int));
int	print_lines ANSI((char *,int));
void	page_init ANSI((void));
void	pad ANSI((int));
void	printcmd ANSI((void));
void	rubout ANSI((void));
void	reprint ANSI((void));
#ifdef CLEAREOL
void	home_cursor ANSI((void));
#endif
#ifdef SIGWINCH
SIGRET	winch_catcher ANSI((int));
#endif /* SIGWINCH */
!STUFFY!FUNK!
echo Extracting artio.h
cat >artio.h <<'!STUFFY!FUNK!'
/* $Id: artio.h,v 4.4 1991/09/09 20:18:23 sob Exp sob $
 *
 * $Log: artio.h,v $
 * Revision 4.4  1991/09/09  20:18:23  sob
 * release 4.4
 *
 *
 * 
 */
/* This software is Copyright 1991 by Stan Barber. 
 *
 * Permission is hereby granted to copy, reproduce, redistribute or otherwise
 * use this software as long as: there is no monetary profit gained
 * specifically from the use or reproduction of this software, it is not
 * sold, rented, traded or otherwise marketed, and this copyright notice is
 * included prominently in any copy made. 
 *
 * The author make no claims as to the fitness or correctness of this software
 * for any use whatsoever, and it is provided as is. Any use of this software
 * is at the user's own risk. 
 */

EXT ART_POS artpos INIT(0);	/* byte position in article file */

EXT ART_LINE artline INIT(0);		/* current line number in article file */
EXT FILE *artfp INIT(Nullfp);		/* current article file pointer */
EXT ART_NUM openart INIT(0);		/* what is the currently open article number? */
#ifdef LINKART
    EXT char *linkartname INIT(nullstr);/* real name of article for Eunice */
#endif
#ifdef SERVER
EXT ART_PART openpart INIT(0);	/* how much of that article do we have? */
FILE	*nntpopen ANSI((ART_NUM,ART_PART));
				/* get an article unless already retrieved */
void	nntpclose ANSI((void));
/* MUST be in increasing order of completeness! */
#define GET_STATUS	1		/* test for existence only */
#define GET_HEADER	2		/* if only header items are desired */
#define GET_ARTICLE	3		/* retreive full article  */
#endif

void	artio_init ANSI((void));
FILE	*artopen ANSI((ART_NUM));  /* open an article unless already opened */
!STUFFY!FUNK!
echo ""
echo "End of kit 7 (of 11)"
cat /dev/null >kit7isdone
config=true
for iskit in 1 2 3 4 5 6 7 8 9 10 11 ; 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
