rn version 4.3 (kit 4 of 9)

sources-request at genrad.UUCP sources-request at genrad.UUCP
Sat May 11 07:00:09 AEST 1985


From: lwall at sdcrdcf.UUCP (Larry Wall)

---------------- cut here ---------------
#! /bin/sh

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

echo "This is rn kit 4 (of 9).  If kit 4 is complete, the line"
echo '"'"End of kit 4 (of 9)"'" will echo at the end.'
echo ""
export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
echo Extracting ng.c
cat >ng.c <<'!STUFFY!FUNK!'
/* $Header: ng.c,v 4.3 85/05/01 11:43:43 lwall Exp $
 *
 * $Log:	ng.c,v $
 * Revision 4.3  85/05/01  11:43:43  lwall
 * Baseline for release with 4.3bsd.
 * 
 */

#include "EXTERN.h"
#include "common.h"
#include "rn.h"
#include "term.h"
#include "final.h"
#include "util.h"
#include "artsrch.h"
#include "cheat.h"
#include "help.h"
#include "kfile.h"
#include "rcstuff.h"
#include "head.h"
#include "artstate.h"
#include "bits.h"
#include "art.h"
#include "artio.h"
#include "ngstuff.h"
#include "intrp.h"
#include "respond.h"
#include "ngdata.h"
#include "backpage.h"
#include "rcln.h"
#include "last.h"
#include "INTERN.h"
#include "ng.h"
#include "artstate.h"			/* somebody has to do it */

/* art_switch() return values */

#define AS_NORM 0
#define AS_INP 1
#define AS_ASK 2
#define AS_CLEAN 3

ART_NUM recent_art = 0;		/* previous article # for '-' command */
ART_NUM curr_art = 0;                /* current article # */
int exit_code = NG_NORM;

void
ng_init()
{

#ifdef KILLFILES
    open_kfile(KF_GLOBAL);
#endif
}

/* do newsgroup on line ng with name ngname */

/* assumes that we are chdir'ed to SPOOL, and assures that that is
 * still true upon return, but chdirs to SPOOL/ngname in between
 *
 * If you can understand this routine, you understand most of the program.
 * The basic structure is:
 *	for each desired article
 *		for each desired page
 *			for each line on page
 *				if we need another line from file
 *					get it
 *					if it's a header line
 *						do special things
 *				for each column on page
 *					put out a character
 *				end loop
 *			end loop
 *		end loop
 *	end loop
 *
 *	(Actually, the pager is in another routine.)
 *
 * The chief problem is deciding what is meant by "desired".  Most of
 * the messiness of this routine is due to the fact that people want
 * to do unstructured things all the time.  I have used a few judicious
 * goto's where I thought it improved readability.  The rest of the messiness
 * arises from trying to be both space and time efficient.  Have fun.
 */

int
do_newsgroup(start_command)
char *start_command;			/* command to fake up first */
{
    char oldmode = mode;
    register long i;			/* scratch */
    int skipstate;			/* how many unavailable articles */
					/*   have we skipped already? */
    
    char *whatnext = "%sWhat next? [%s]";

#ifdef ARTSEARCH
    srchahead = (scanon && ((ART_NUM)toread[ng]) >= scanon ? -1 : 0);
					/* did they say -S? */
#endif
    
    mode = 'a';
    recent_art = curr_art = 0;
    exit_code = NG_NORM;
    if (eaccess(ngdir,5)) {		/* directory read protected? */
	if (eaccess(ngdir,0)) {
#ifdef VERBOSE
	    IF(verbose)
		printf("\nNewsgroup %s does not have a spool directory!\n",
		    ngname) FLUSH;
	    ELSE
#endif
#ifdef TERSE
		printf("\nNo spool for %s!\n",ngname) FLUSH;
#endif
#ifdef CATCHUP
	    catch_up(ng);
#endif
	    toread[ng] = TR_NONE;
	}
	else {
#ifdef VERBOSE
	    IF(verbose)
		printf("\nNewsgroup %s is not currently accessible.\n",
		    ngname) FLUSH;
	    ELSE
#endif
#ifdef TERSE
		printf("\n%s not readable.\n",ngname) FLUSH;
#endif
	    toread[ng] = TR_NONE;	/* make this newsgroup invisible */
					/* (temporarily) */
	}
	mode = oldmode;
	return -1;
    }

    /* chdir to newsgroup subdirectory */

    if (chdir(ngdir)) {
	printf(nocd,ngdir) FLUSH;
	mode = oldmode;
	return -1;
    }

#ifdef CACHESUBJ
    subj_list = Null(char **);		/* no subject list till needed */
#endif
    
    /* initialize control bitmap */

    if (initctl()) {
	mode = oldmode;
	return -1;
    }

    /* FROM HERE ON, RETURN THRU CLEANUP OR WE ARE SCREWED */
    
    in_ng = TRUE;			/* tell the world we are here */
    forcelast = TRUE;			/* if 0 unread, do not bomb out */
    art=firstart;
    
    /* remember what newsgroup we were in for sake of posterity */

    writelast();

    /* do they want a special top line? */

    firstline = getval("FIRSTLINE",Nullch);

    /* see if there are any special searches to do */

#ifdef KILLFILES
    open_kfile(KF_LOCAL);
#ifdef VERBOSE
    IF(verbose)
	kill_unwanted(firstart,"Looking for articles to kill...\n\n",TRUE);
    ELSE
#endif
#ifdef TERSE
	kill_unwanted(firstart,"Killing...\n\n",TRUE);
#endif
#endif
    
    /* now read each unread article */

    rc_changed = doing_ng = TRUE;	/* enter the twilight zone */
    skipstate = 0;			/* we have not skipped anything (yet) */
    checkcount = 0;			/* do not checkpoint for a while */
    do_fseek = FALSE;			/* start 1st article at top */
    if (art > lastart)
	art=firstart;			/* init the for loop below */
    for (; art<=lastart+1; ) {		/* for each article */

	/* do we need to "grow" the newsgroup? */

	if (art > lastart || forcegrow)
	    grow_ctl();
	check_first(art);		/* make sure firstart is still 1st */
	if (start_command) {		/* fake up an initial command? */
	    prompt = whatnext;
	    strcpy(buf,start_command);
	    free(start_command);
	    start_command = Nullch;
	    art = lastart+1;
	    goto article_level;
	}
	if (art>lastart) {		/* are we off the end still? */
	    ART_NUM ucount = 0;		/* count of unread articles left */

	    for (i=firstart; i<=lastart; i++)
		if (!(ctl_read(i)))
		    ucount++;		/* count the unread articles */
#ifdef DEBUGGING
	    /*NOSTRICT*/
	    if (debug && ((ART_NUM)toread[ng]) != ucount)
		printf("(toread=%ld sb %ld)",(long)toread[ng],(long)ucount)
		  FLUSH;
#endif
	    /*NOSTRICT*/
	    toread[ng] = (ART_UNREAD)ucount;	/* this is perhaps pointless */
	    art = lastart + 1;		/* keep bitmap references sane */
	    if (art != curr_art) {
		recent_art = curr_art;
					/* remember last article # (for '-') */
		curr_art = art;      /* remember this article # */
	    }
	    if (erase_screen)
		clear();			/* clear the screen */
	    else
		fputs("\n\n",stdout) FLUSH;
#ifdef VERBOSE
	    IF(verbose)
		printf("End of newsgroup %s.",ngname);
					/* print pseudo-article */
	    ELSE
#endif
#ifdef TERSE
		printf("End of %s",ngname);
#endif
	    if (ucount) {
		printf("  (%ld article%s still unread)",
		    (long)ucount,ucount==1?nullstr:"s");
	    }
	    else {
		if (!forcelast)
		    goto cleanup;	/* actually exit newsgroup */
	    }
	    prompt = whatnext;
#ifdef ARTSEARCH
	    srchahead = 0;		/* no more subject search mode */
#endif
	    fputs("\n\n",stdout) FLUSH;
	    skipstate = 0;		/* back to none skipped */
	}
	else if (!reread && was_read(art)) {
					/* has this article been read? */
	    art++;			/* then skip it */
	    continue;
	}
	else if
	  (!reread && !was_read(art)
	    && artopen(art) == Nullfp) {	/* never read it, & cannot find it? */
	    if (errno != ENOENT) {	/* has it not been deleted? */
#ifdef VERBOSE
		IF(verbose)
		    printf("\n(Article %ld exists but is unreadable.)\n",
			(long)art) FLUSH;
		ELSE
#endif
#ifdef TERSE
		    printf("\n(%ld unreadable.)\n",(long)art) FLUSH;
#endif
		skipstate = 0;
		sleep(2);
	    }
	    switch(skipstate++) {
	    case 0:
		clear();
#ifdef VERBOSE
		IF(verbose)
		    fputs("Skipping unavailable article",stdout);
		ELSE
#endif
#ifdef TERSE
		    fputs("Skipping",stdout);
#endif
		for (i = just_a_sec/3; i; --i)
		    putchar(PC);
		fflush(stdout);
		sleep(1);
		break;
	    case 1:
		fputs("..",stdout);
		fflush(stdout);
		break;
	    default:
		putchar('.');
		fflush(stdout);
#define READDIR
#ifdef READDIR
		{			/* fast skip patch */
		    ART_NUM newart;
		    
		    if (! (newart=getngmin(".",art)))
			newart = lastart+1;
		    for (i=art; i<newart; i++)
			oneless(i);
		    art = newart - 1;
		}
#endif
		break;
	    }
	    oneless(art);		/* mark deleted as read */
	    art++;			/* try next article */
	    continue;
	}
	else {				/* we have a real live article */
	    skipstate = 0;		/* back to none skipped */
	    if (art != curr_art) {
		recent_art = curr_art;
					/* remember last article # (for '-') */
		curr_art = art;      /* remember this article # */
	    }
	    if (!do_fseek) {		/* starting at top of article? */
		artline = 0;		/* start at the beginning */
		topline = -1;		/* and remember top line of screen */
					/*  (line # within article file) */
	    }
	    clear();			/* clear screen */
	    artopen(art);		/* make sure article file is open */
	    if (artfp == Nullfp) {	/* could not find article? */
		printf("Article %ld of %s is not available.\n\n",
		    (long)art,ngname) FLUSH;
		prompt = whatnext;
#ifdef ARTSEARCH
		srchahead = 0;
#endif
	    }
	    else {			/* found it, so print it */
		switch (do_article()) {
		case DA_CLEAN:		/* quit newsgroup */
		    goto cleanup;
		case DA_TOEND:		/* do not mark as read */
		    goto reask_article; 
		case DA_RAISE:		/* reparse command at end of art */
		    goto article_level;
		case DA_NORM:		/* normal end of article */
		    break;
		}
	    }
	    mark_as_read(art);		 /* mark current article as read */
	    reread = FALSE;
	    do_hiding = TRUE;
#ifdef ROTATION
	    rotate = FALSE;
#endif
	}

/* if these gotos bother you, think of this as a little state machine */

reask_article:
#ifdef MAILCALL
	setmail();
#endif
	setdfltcmd();
#ifdef CLEAREOL
	if (erase_screen && can_home_clear)	/* PWP was here */
	    clear_rest();
#endif CLEAREOL
	unflush_output();		/* disable any ^O in effect */
	standout();			/* enter standout mode */
	printf(prompt,mailcall,dfltcmd);/* print prompt, whatever it is */
	un_standout();			/* leave standout mode */
	putchar(' ');
	fflush(stdout);
reinp_article:
	eat_typeahead();
#ifdef PENDING
	look_ahead();			/* see what we can do in advance */
	if (!input_pending())
	    collect_subjects();		/* loads subject cache until */
					/* input is pending */
#endif
	getcmd(buf);
	if (errno || *buf == '\f') {
	    if (LINES < 100 && !int_count)
		*buf = '\f';		/* on CONT fake up refresh */
	    else {
		putchar('\n') FLUSH;		/* but only on a crt */
		goto reask_article;
	    }
	}
article_level:

	/* parse and process article level command */

	switch (art_switch()) {
	case AS_INP:			/* multichar command rubbed out */
	    goto reinp_article;
	case AS_ASK:			/* reprompt "End of article..." */
	    goto reask_article;
	case AS_CLEAN:			/* exit newsgroup */
	    goto cleanup;
	case AS_NORM:			/* display article art */
	    break;
	}
    }					/* end of article selection loop */
    
/* shut down newsgroup */

cleanup:
#ifdef KILLFILES
    kill_unwanted(firstart,"\nCleaning up...\n\n",FALSE);
					/* do cleanup from KILL file, if any */
#endif
    in_ng = FALSE;			/* leave newsgroup state */
    if (artfp != Nullfp) {		/* article still open? */
	fclose(artfp);			/* close it */
	artfp = Nullfp;			/* and tell the world */
	openart = 0;
    }
    putchar('\n') FLUSH;
    yankback();				/* do a Y command */
    restore_ng();			/* reconstitute .newsrc line */
    doing_ng = FALSE;			/* tell sig_catcher to cool it */
    free(ctlarea);			/* return the control area */
#ifdef CACHESUBJ
    if (subj_list) {
	for (i=OFFSET(lastart); i>=0; --i)
	    if (subj_list[i])
		free(subj_list[i]);
#ifndef lint
	free((char*)subj_list);
#endif lint
    }
#endif
    write_rc();				/* and update .newsrc */
    rc_changed = FALSE;			/* tell sig_catcher it is ok */
    if (chdir(spool)) {
	printf(nocd,spool) FLUSH;
	sig_catcher(0);
    }
#ifdef KILLFILES
    if (localkfp) {
	fclose(localkfp);
	localkfp = Nullfp;
    }
#endif
    mode = oldmode;
    return exit_code;
}					/* Whew! */

/* decide what to do at the end of an article */

int
art_switch()
{
    register ART_NUM i;
      
    setdef(buf,dfltcmd);
#ifdef VERIFY
    printcmd();
#endif
    switch (*buf) {
    case 'p':			/* find previous unread article */
	do {
	    if (art <= firstart)
		break;
	    art--;
	} while (was_read(art) || artopen(art) == Nullfp);
#ifdef ARTSEARCH
	srchahead = 0;
#endif
	return AS_NORM;
    case 'P':			/* goto previous article */
	if (art > absfirst)
	    art--;
	else {
#ifdef VERBOSE
	    IF(verbose)
		fputs("\n\
There are no articles prior to this one.\n\
",stdout) FLUSH;
	    ELSE
#endif
#ifdef TERSE
		fputs("\nNo previous articles\n",stdout) FLUSH;
#endif
	    return AS_ASK;
	}
	reread = TRUE;
#ifdef ARTSEARCH
	srchahead = 0;
#endif
	return AS_NORM;
    case '-':
	if (recent_art) {
	    art = recent_art;
	    reread = TRUE;
#ifdef ARTSEARCH
	    srchahead = -(srchahead != 0);
#endif
	    return AS_NORM;
	}
	else {
	    exit_code = NG_MINUS;
	    return AS_CLEAN;
	}
    case 'n':		/* find next unread article? */
	if (art > lastart) {
	    if (toread[ng])
		art = firstart;
	    else
		return AS_CLEAN;
	}
#ifdef ARTSEARCH
	else if (scanon && srchahead) {
	    *buf = Ctl('n');
	    goto normal_search;
	}
#endif
	else
	    art++;
#ifdef ARTSEARCH
	srchahead = 0;
#endif
	return AS_NORM;
    case 'N':			/* goto next article */
	if (art > lastart)
	    art = absfirst;
	else
	    art++;
	if (art <= lastart)
	    reread = TRUE;
#ifdef ARTSEARCH
	srchahead = 0;
#endif
	return AS_NORM;
    case '$':
	art = lastart+1;
	forcelast = TRUE;
#ifdef ARTSEARCH
	srchahead = 0;
#endif
	return AS_NORM;
    case '1': case '2': case '3':	/* goto specified article */
    case '4': case '5': case '6':	/* or do something with a range */
    case '7': case '8': case '9': case '.':
	forcelast = TRUE;
	switch (numnum()) {
	case NN_INP:
	    return AS_INP;
	case NN_ASK:
	    return AS_ASK;
	case NN_REREAD:
	    reread = TRUE;
#ifdef ARTSEARCH
	    if (srchahead)
		srchahead = -1;
#endif
	    break;
	case NN_NORM:
	    if (was_read(art)) {
		art = firstart;
		pad(just_a_sec/3);
	    }
	    else
		return AS_ASK;
	    break;
	}
	return AS_NORM;
    case Ctl('k'):
	edit_kfile();
	return AS_ASK;
    case 'K':
    case 'k':
    case Ctl('n'): case Ctl('p'):
    case '/': case '?':
#ifdef ARTSEARCH
normal_search:
    {		/* search for article by pattern */
	char cmd = *buf;
	
	reread = TRUE;		/* assume this */
	switch (art_search(buf, (sizeof buf), TRUE)) {
	case SRCH_ERROR:
	    return AS_ASK;
	case SRCH_ABORT:
	    return AS_INP;
	case SRCH_INTR:
#ifdef VERBOSE
	    IF(verbose)
		printf("\n(Interrupted at article %ld)\n",(long)art) FLUSH;
	    ELSE
#endif
#ifdef TERSE
		printf("\n(Intr at %ld)\n",(long)art) FLUSH;
#endif
	    art = curr_art;
			    /* restore to current article */
	    return AS_ASK;
	case SRCH_DONE:
	    fputs("done\n",stdout) FLUSH;
	    pad(just_a_sec/3);	/* 1/3 second */
	    if (srchahead)
		art = firstart;
	    else
		art = curr_art;
	    reread = FALSE;
	    return AS_NORM;
	case SRCH_SUBJDONE:
#ifdef UNDEF
	    fputs("\n\n\n\nSubject not found.\n",stdout) FLUSH;
	    pad(just_a_sec/3);	/* 1/3 second */
#endif
	    art = firstart;
	    reread = FALSE;
	    return AS_NORM;
	case SRCH_NOTFOUND:
	    fputs("\n\n\n\nNot found.\n",stdout) FLUSH;
	    art = curr_art;  /* restore to current article */
	    return AS_ASK;
	case SRCH_FOUND:
	    if (cmd == Ctl('n') || cmd == Ctl('p'))
		oldsubject = TRUE;
	    break;
	}
	return AS_NORM;
    }
#else
    buf[1] = '\0';
    notincl(buf);
    return AS_ASK;
#endif
    case 'u':			/* unsubscribe from this newsgroup? */
	rcchar[ng] = NEGCHAR;
	return AS_CLEAN;
    case 'M':
#ifdef DELAYMARK
	if (art <= lastart) {
	    delay_unmark(art);
	    printf("\nArticle %ld will return.\n",(long)art) FLUSH;
	}
#else
	notincl("M");
#endif
	return AS_ASK;
    case 'm':
	if (art <= lastart) {
	    unmark_as_read(art);
	    printf("\nArticle %ld marked as still unread.\n",(long)art) FLUSH;
	}
	return AS_ASK;
    case 'c':			/* catch up */
      reask_catchup:
#ifdef VERBOSE
	IF(verbose)
	    in_char("\nDo you really want to mark everything as read? [yn] ");
	ELSE
#endif
#ifdef TERSE
	    in_char("\nReally? [ynh] ");
#endif
	putchar('\n') FLUSH;
	setdef(buf,"y");
#ifdef VERIFY
	printcmd();
#endif
	if (*buf == 'h') {
#ifdef VERBOSE
	    IF(verbose)
		fputs("\
Type y or SP to mark all articles as read.\n\
Type n to leave articles marked as they are.\n\
Type u to mark everything read and unsubsubscribe.\n\
",stdout) FLUSH;
	    ELSE
#endif
#ifdef TERSE
		fputs("\
y or SP to mark all read.\n\
n to forget it.\n\
u to mark all and unsubscribe.\n\
",stdout) FLUSH;
#endif
	    goto reask_catchup;
	}
	else if (*buf == 'n' || *buf == 'q') {
	    return AS_ASK;
	}
	else if (*buf != 'y' && *buf != 'u') {
	    fputs(hforhelp,stdout) FLUSH;
	    settle_down();
	    goto reask_catchup;
	}
	for (i = firstart; i <= lastart; i++) {
	    ctl_set(i);		/* mark as read */
	}
#ifdef DELAYMARK
	if (dmfp)
	    yankback();
#endif
	if (*buf == 'u') {
	    rcchar[ng] = NEGCHAR;
	    return AS_CLEAN;
	}
	art = lastart+1;
	forcelast = FALSE;
	return AS_NORM;
    case 'Q':
	exit_code = NG_ASK;
	/* FALL THROUGH */
    case 'q':			/* go back up to newsgroup level? */
	return AS_CLEAN;
    case 'j':
	putchar('\n') FLUSH;
	if (art <= lastart)
	    mark_as_read(art);
	return AS_ASK;
    case 'h': {			/* help? */
	int cmd;

	if ((cmd = help_art()) > 0)
	    pushchar(cmd);
	return AS_ASK;
    }
    case '&':
	if (switcheroo()) /* get rest of command */
	    return AS_INP;	/* if rubbed out, try something else */
	return AS_ASK;
    case '#':
#ifdef VERBOSE
	IF(verbose)
	    printf("\nThe last article is %ld.\n",(long)lastart) FLUSH;
	ELSE
#endif
#ifdef TERSE
	    printf("\n%ld\n",(long)lastart) FLUSH;
#endif
	return AS_ASK;
    case '=': {
	char tmpbuf[256];
	ART_NUM oldart = art;
	int cmd;
	char *subjline = getval("SUBJLINE",Nullch);
#ifndef CACHESUBJ
	char *s;
#endif
	
	page_init();
#ifdef CACHESUBJ
	if (!subj_list)
	    fetchsubj(art,TRUE,FALSE);
#endif
	for (i=firstart; i<=lastart && !int_count; i++) {
#ifdef CACHESUBJ
	    if (!was_read(i) &&
	      (subj_list[OFFSET(i)] != Nullch || fetchsubj(i,FALSE,FALSE)) &&
	      *subj_list[OFFSET(i)] ) {
		sprintf(tmpbuf,"%5ld ", i);
		if (subjline) {
		    art = i;
		    interp(tmpbuf + 6, (sizeof tmpbuf) - 6, subjline);
		}
		else
		    safecpy(tmpbuf + 6, subj_list[OFFSET(i)],
			(sizeof tmpbuf) - 6);
		if (cmd = print_lines(tmpbuf,NOMARKING)) {
		    if (cmd > 0)
			pushchar(cmd);
		    break;
		}
	    }
#else
	    if (!was_read(i) && (s = fetchsubj(i,FALSE,FALSE)) && *s) {
		sprintf(tmpbuf,"%5ld ", i);
		if (subjline) {	/* probably fetches it again! */
		    art = i;
		    interp(tmpbuf + 6, (sizeof tmpbuf) - 6, subjline);
		}
		else
		    safecpy(tmpbuf + 6, s, (sizeof tmpbuf) - 6);
		if (cmd = print_lines(tmpbuf,NOMARKING)) {
		    if (cmd > 0)
			pushchar(cmd);
		    break;
		}
	    }
#endif
	}
	int_count = 0;
	art = oldart;
	return AS_ASK;
    }
    case '^':
	art = firstart;
#ifdef ARTSEARCH
	srchahead = 0;
#endif
	return AS_NORM;
#if defined(CACHESUBJ) && defined(DEBUGGING)
    case 'D':
	printf("\nFirst article: %ld\n",(long)firstart) FLUSH;
	if (!subj_list)
	    fetchsubj(art,TRUE,FALSE);
	if (subj_list != Null(char **)) {
	    for (i=1; i<=lastart && !int_count; i++) {
		if (subj_list[OFFSET(i)])
		    printf("%5ld %c %s\n",
			i, (was_read(i)?'y':'n'), subj_list[OFFSET(i)]) FLUSH;
	    }
	}
	int_count = 0;
	return AS_ASK;
#endif
    case 'v':
	if (art <= lastart) {
	    reread = TRUE;
	    do_hiding = FALSE;
	}
	return AS_NORM;
#ifdef ROTATION
    case Ctl('x'):
#endif
    case Ctl('r'):
#ifdef ROTATION
	rotate = (*buf==Ctl('x'));
#endif
	if (art <= lastart)
	    reread = TRUE;
	return AS_NORM;
#ifdef ROTATION
    case 'X':
	rotate = !rotate;
	/* FALL THROUGH */
#else
    case Ctl('x'):
    case 'x':
    case 'X':
	notincl("x");
	return AS_ASK;
#endif
    case 'l': case Ctl('l'):		/* refresh screen */
	if (art <= lastart) {
	    reread = TRUE;
	    clear();
	    do_fseek = TRUE;
	    artline = topline;
	    if (artline < 0)
		artline = 0;
	}
	return AS_NORM;
    case 'b': case Ctl('b'):		/* back up a page */
	if (art <= lastart) {
	    ART_LINE target;

	    reread = TRUE;
	    clear();
	    do_fseek = TRUE;
	    target = topline - (LINES - 2);
	    artline = topline;
	    do {
		artline--;
	    } while (artline >= 0 && artline > target &&
		vrdary(artline-1) >= 0);
	    topline = artline;
	    if (artline < 0)
		artline = 0;
	}
	return AS_NORM;
    case '!':			/* shell escape */
	if (escapade())
	    return AS_INP;
	return AS_ASK;
    case 'C': {
	cancel_article();
	return AS_ASK;
    }
    case 'R':
    case 'r': {			/* reply? */
	reply();
	return AS_ASK;
    }
    case 'F':
    case 'f': {			/* followup command */
	followup();
	forcegrow = TRUE;		/* recalculate lastart */
	return AS_ASK;
    }
    case '|':
    case 'w': case 'W':
    case 's': case 'S':		/* save command */
	if (save_article() == SAVE_ABORT)
	    return AS_INP;
	return AS_ASK;
#ifdef DELAYMARK
    case 'Y':				/* yank back M articles */
	yankback();
	art = firstart;			/* from the beginning */
	return AS_NORM;			/* pretend nothing happened */
#endif
#ifdef STRICTCR
    case '\n':
	fputs(badcr,stdout) FLUSH;
	return AS_ASK;
#endif
    default:
	printf("\n%s",hforhelp) FLUSH;
	settle_down();
	return AS_ASK;
    }
}

#ifdef MAILCALL
/* see if there is any mail */

void
setmail()
{
    if (! (mailcount++)) {
	char *mailfile = filexp(getval("MAILFILE",MAILFILE));
	
	if (stat(mailfile,&filestat) < 0 || !filestat.st_size
	    || filestat.st_atime > filestat.st_mtime)
	    mailcall = nullstr;
	else
	    mailcall = "(Mail) ";
    }
    mailcount %= 10;			/* check every 10 articles */
}
#endif

void
setdfltcmd()
{
    if (toread[ng]) {
#ifdef ARTSEARCH
	if (srchahead)
	    dfltcmd = "^Nnpq";
	else
#endif
	    dfltcmd = "npq";
    }
    else {
	if (art > lastart)
	    dfltcmd = "qnp";
	else
	    dfltcmd = "npq";
    }
}

!STUFFY!FUNK!
echo Extracting art.c
cat >art.c <<'!STUFFY!FUNK!'
/* $Header: art.c,v 4.3 85/05/01 11:34:51 lwall Exp $
 *
 * $Log:	art.c,v $
 * Revision 4.3  85/05/01  11:34:51  lwall
 * Baseline for release with 4.3bsd.
 * 
 */

#include "EXTERN.h"
#include "common.h"
#include "rn.h"
#include "ngstuff.h"
#include "head.h"
#include "cheat.h"
#include "help.h"
#include "search.h"
#include "artio.h"
#include "ng.h"
#include "bits.h"
#include "final.h"
#include "artstate.h"
#include "rcstuff.h"
#include "term.h"
#include "sw.h"
#include "util.h"
#include "backpage.h"
#include "intrp.h"
#include "INTERN.h"
#include "art.h"

/* page_switch() return values */

#define PS_NORM 0
#define PS_ASK 1
#define PS_RAISE 2
#define PS_TOEND 3

bool special = FALSE;		/* is next page special length? */
int slines = 0;			/* how long to make page when special */
ART_LINE highlight = -1;	/* next line to be highlighted */
char *restart = Nullch;		/* if nonzero, the place where last */
				/* line left off on line split */
char *blinebeg;			/* where in buffer current line began */
ART_POS alinebeg;		/* where in file current line began */

#ifdef INNERSEARCH
ART_POS innersearch = 0;	/* artpos of end of line we found */
				/* for 'g' command */
ART_LINE isrchline = 0;			/* last line to display */
bool hide_everything = FALSE;
				/* if set, do not write page now, */
				/* but refresh when done with page */
COMPEX gcompex;				/* in article search pattern */
#endif

bool firstpage;			/* is this the 1st page of article? */

void
art_init()
{
    ;
}

int
do_article()
{
    register char *s;
    ART_POS artsize;			/* size in bytes of article */
    char art_buf[LBUFLEN];		/* place for article lines */
    bool hide_this_line = FALSE;	/* hidden header line? */
    ART_LINE linenum;	/* line # on page, 1 origin */
#ifdef ULSMARTS
    bool under_lining = FALSE;
			    /* are we underlining a word? */
#endif
    register char *bufptr = art_buf;
			    /* pointer to input buffer */
    register int outpos;	/* column position of output */
    static char prompt_buf[64];		/* place to hold prompt */
    bool notesfiles = FALSE;		/* might there be notesfiles junk? */
    char oldmode = mode;

#ifdef INNERSEARCH
    register int outputok;
#endif

    if (fstat(artfp->_file,&filestat))
			    /* get article file stats */
	return DA_CLEAN;
    artsize = filestat.st_size;
			    /* from that get article size */
    sprintf(prompt_buf,
	"%%sEnd of article %ld (of %ld)--what next? [%%s]",
	(long)art,(long)lastart);	/* format prompt string */
    prompt = prompt_buf;
    int_count = 0;		/* interrupt count is 0 */
    firstpage = (topline < 0);
    for (;;) {			/* for each page */
	assert(art == openart);
	if (do_fseek) {
#ifdef ASYNC_PARSE
	    parse_maybe(art);		/* make sure header is ours */
#endif
	    artpos = vrdary(artline);
	    if (artpos < 0)
		artpos = -artpos;	/* labs(), anyone? */
	    fseek(artfp,artpos,0);
	    if (artpos < htype[PAST_HEADER].ht_minpos)
		in_header = SOME_LINE;
	    do_fseek = FALSE;
	    restart = Nullch;
	}
	if (firstpage) {
	    if (firstline) {
		interp(art_buf, (sizeof art_buf), firstline);
#ifdef CLEAREOL
		maybe_eol();	/* PWP */
#endif CLEAREOL
		fputs(art_buf,stdout) FLUSH;
		artopen(art);		/* rewind article in case interp */
					/* forced a header parse */
	    }
	    else {
		ART_NUM i;

#ifdef CLEAREOL
		maybe_eol();	/* PWP */
#endif CLEAREOL
		printf("Article %ld",(long)art);
		i = (((ART_NUM)toread[ng]) - 1 + was_read(art));
#ifdef DELAYMARK
		if (i || dmcount) {
		    printf(" (%ld more",(long)i);
		    if (dmcount)
			printf(" + %ld Marked to return)",(long)dmcount);
		    putchar(')');
		}
#else
		if (i)
		    printf(" (%ld more)",(long)i);
#endif
		if (htype[NGS_LINE].ht_flags & HT_HIDE)
		    printf(" in %s", ngname);
		fputs(":\n",stdout) FLUSH;
	    }
	    start_header(art);
	    forcelast = FALSE;		/* we will have our day in court */
	    restart = Nullch;
	    artline = 0;		/* start counting lines */
	    artpos = 0;
	    vwtary(artline,artpos);	/* remember pos in file */
	}
	for (linenum=(firstpage?2:1);
	  in_header || (
#ifdef INNERSEARCH
	  innersearch ? innermore() :
#endif
	  linenum<(firstpage?initlines:(special?slines:LINES)) );
	  linenum++) {		/* for each line on page */
	    if (int_count) {	/* exit via interrupt? */
		putchar('\n') FLUSH;	/* get to left margin */
		int_count = 0;	/* reset interrupt count */
		return DA_NORM;	/* skip out of loops */
	    }
	    if (restart) {		/* did not finish last line? */
		bufptr = restart;	/* then start again here */
		restart = Nullch;	/* and reset the flag */
	    }
	    else {			/* not a restart */
		if (fgets(art_buf,LBUFLEN,artfp)==Nullch) {
					/* if all done */
		    return DA_NORM;	/* skip out of loops */
		}
		bufptr = art_buf;	/* so start at beginning */
		art_buf[LBUFLEN-1] = '\0';
					/* make sure string ends */
	    }
	    blinebeg = bufptr;	/* remember where we began */
	    alinebeg = artpos;	/* both in buffer and file */
	    if (in_header && bufptr == art_buf)
		hide_this_line =
		    parseline(art_buf,do_hiding,hide_this_line);
	    else if (notesfiles && do_hiding &&
	      bufptr == art_buf && *art_buf == '#' &&
	      isupper(art_buf[1]) && art_buf[2] == ':' ) {
		fgets(art_buf,sizeof(art_buf),artfp);
		if (index(art_buf,'!') != Nullch)
		    fgets(art_buf,sizeof(art_buf),artfp);
		htype[PAST_HEADER].ht_minpos = ftell(artfp);
					/* exclude notesfiles droppings */
		hide_this_line = TRUE;	/* and do not print either */
		notesfiles = FALSE;
	    }
	    if (in_header && htype[in_header].ht_flags & HT_MAGIC) {
		if (in_header == NGS_LINE) {
		    hide_this_line = (index(art_buf,',') == Nullch && do_hiding);
		}
		else if (in_header == EXPIR_LINE) {
		    if (!(htype[EXPIR_LINE].ht_flags & HT_HIDE))
		    hide_this_line = (strlen(art_buf) < 10 && do_hiding);
		}
	    }
	    if (in_header == SUBJ_LINE &&
		htype[SUBJ_LINE].ht_flags & HT_MAGIC) {
			    /* is this the subject? */
		int length;

		length = strlen(art_buf)-1;
		artline++;
		art_buf[length] = '\0';		/* wipe out newline */
#ifdef NOFIREWORKS
		no_ulfire();
#endif
		notesfiles =
		    (instr(&art_buf[length-10]," - (nf") != Nullch);
		if (oldsubject) {
		    length += 7;
		    fputs("(SAME) ",stdout);
		    oldsubject = FALSE;
		}
		if (length+UG > COLS) {		/* rarely true */
		    linenum++;
		    vwtary(artline,vrdary(artline-1)+COLS);
		    artline++;
		}
		s = art_buf + 8;
		*s++ = '\0';	/* make into 2 strings */
#ifdef CLEAREOL
		maybe_eol();	/* PWP */
#endif CLEAREOL
		fputs(art_buf,stdout) FLUSH;
				/* print up through : */
		if (!UG)
		    putchar(' ');
		underprint(s);	/* print subject underlined */
		putchar('\n') FLUSH;	/* and finish the line */
	    }
	    else if (hide_this_line) {	/* do not print line? */
		linenum--;		/* compensate for linenum++ */
		if (!in_header)
		    hide_this_line = FALSE;
	    }
	    else {			/* just a normal line */
		if (highlight==artline) {	/* this line to be highlit? */
		    if (marking == STANDOUT) {
#ifdef NOFIREWORKS
			if (erase_screen)
			    no_sofire();
#endif
			standout();
		    }
		    else {
#ifdef NOFIREWORKS
			if (erase_screen)
			    no_ulfire();
#endif
			underline();
		    }
		    if (*bufptr == '\n')
			putchar(' ');
		}
#ifdef INNERSEARCH
		outputok = !hide_everything;
					/* get it into register, hopefully */
#endif
#ifdef CLEAREOL
#ifdef INNERSEARCH
		if (outputok)
#endif
		maybe_eol();	/* PWP */
#endif CLEAREOL
		for (outpos = 0; outpos < COLS; ) {
				    /* while line has room */
		    if (*bufptr >= ' ') {	/* normal char? */
#ifdef ULSMARTS
			if (*bufptr == '_') {
			    if (bufptr[1] == '\b') {
				if (!under_lining && highlight!=artline
#ifdef INNERSEARCH
				    && outputok
#endif
				    ) {
				    under_lining++;
				    if (UG) {
					if (bufptr != buf &&
					  bufptr[-1] == ' ') {
					    outpos--;
					    backspace();
					}
				    }
				    underline();
				}
				bufptr += 2;
			    }
			}
			else {
			    if (under_lining) {
				under_lining = 0;
				un_underline();
				if (UG) {
				    if (*bufptr == ' ')
					goto skip_put;
				    outpos++;
				}
			    }
			}
#endif
#ifdef INNERSEARCH
			if (outputok)
#endif
			{
#ifdef ROTATION
			    if (rotate && !in_header
			      && isalpha(*bufptr)) {
				if ((*bufptr & 31) <= 13)
				    putchar(*bufptr+13);
				else
				    putchar(*bufptr-13);
			    }
			    else
#endif
				putchar(*bufptr);
			}
			if (*UC && ((highlight==artline && marking == 1)
#ifdef ULSMARTS
			    || under_lining
#endif
			    )) {
			    backspace();
			    underchar();
			}
		    skip_put:
			bufptr++;
			outpos++;
		    }
		    else if (*bufptr == '\n' || !*bufptr) {
						    /* newline? */
#ifdef ULSMARTS
			if (under_lining) {
			    under_lining = 0;
			    un_underline();
			}
#endif
#ifdef DEBUGGING
			if (debug & DEB_INNERSRCH && outpos < COLS - 6) {
			    standout();
			    printf("%4d",artline); 
			    un_standout();
			}
#endif
#ifdef INNERSEARCH
			if (outputok)
#endif
			    putchar('\n') FLUSH;
			restart = 0;
			outpos = 1000;	/* signal normal \n */
		    }
		    else if (*bufptr == '\t') {	/* tab? */
#ifdef INNERSEARCH
			if (outputok)
#endif
			    putchar(*bufptr);
			bufptr++;
			outpos += 8 - outpos % 8;
		    }
		    else if (*bufptr == '\f') {	/* form feed? */
#ifdef INNERSEARCH
			if (outputok)
#endif
			    fputs("^L",stdout);
			if (bufptr == blinebeg && highlight != artline)
			    linenum = 32700;
			    /* how is that for a magic number? */
			bufptr++;
			outpos += 2;
		    }
		    else {		/* other control char */
#ifdef INNERSEARCH
			if (outputok)
#endif
			{
			    putchar('^');
			    if (highlight == artline && *UC && marking == 1) {
				backspace();
				underchar();
				putchar(*bufptr+64);
				backspace();
				underchar();
			    }
			    else
				putchar(*bufptr+64);
			}
			bufptr++;
			outpos += 2;
		    }
		    
		} /* end of column loop */

		if (outpos < 1000) {/* did line overflow? */
		    restart = bufptr;
				    /* restart here next time */
		    if (AM) {	/* automatic margins on tty? */
			if (!XN && *bufptr == '\n')
				    /* need we simulate XN? */
			    restart = 0;
				    /* skip the newline */
		    }
		    else {		/* cursor just hangs there */
#ifdef INNERSEARCH
			if (outputok)
#endif
			    putchar('\n') FLUSH;
				    /* so move it down ourselves */
			if (*bufptr == '\n')
			    restart = 0;
				    /* simulate XN if need be */
		    }
#ifdef CLEAREOL
/* #ifdef INNERSEARCH
		    if (outputok)
#endif
		    maybe_eol(); */	/* PWP *//* comment this out for now
						    until I am sure it is
						    needed*/

#endif CLEAREOL
		}

		/* handle normal end of output line formalities */

		if (highlight == artline) {
					/* were we highlighting line? */
		    if (marking == STANDOUT)
			un_standout();
		    else
			un_underline();
		    highlight = -1;	/* no more we are */
		}
		artline++;	/* count the line just printed */
		if (artline - LINES + 1 > topline)
			    /* did we just scroll top line off? */
		    topline = artline - LINES + 1;
			    /* then recompute top line # */
	    }

	    /* determine actual position in file */

	    if (restart)	/* stranded somewhere in the buffer? */
		artpos += restart - blinebeg;
			    /* just calculate position */
	    else		/* no, ftell will do */
		artpos = ftell(artfp);
			    /* so do ftell */
	    vwtary(artline,artpos);	/* remember pos in file */
	} /* end of line loop */

#ifdef INNERSEARCH
	innersearch = 0;
	if (hide_everything) {
	    hide_everything = FALSE;
	    *buf = Ctl('l');
	    goto fake_command;
	}
#endif
	if (linenum >= 32700)/* did last line have formfeed? */
	    vwtary(artline-1,-vrdary(artline-1));
			    /* remember by negating pos in file */

	special = FALSE;	/* end of page, so reset page length */
	firstpage = FALSE;	/* and say it is not 1st time thru */

	/* extra loop bombout */

	if (artpos == artsize)	/* did we just now reach EOF? */
	    return DA_NORM;	/* avoid --MORE--(100%) */

/* not done with this article, so pretend we are a pager */

reask_pager:		    
	unflush_output();	/* disable any ^O in effect */
	standout();		/* enter standout mode */
	printf("--MORE--(%ld%%)",(long)(artpos*100/artsize));
	un_standout();	/* leave standout mode */
	fflush(stdout);
/* reinp_pager:     			/* unused, commented for lint */
	eat_typeahead();
#ifdef DEBUGGING
	if (debug & DEB_CHECKPOINTING) {
	    printf("(%d %d %d)",checkcount,linenum,artline);
	    fflush(stdout);
	}
#endif
	if (checkcount >= docheckwhen &&
	  linenum == LINES &&
	  (artline > 40 || checkcount >= docheckwhen+10) ) {
			    /* while he is reading a whole page */
			    /* in an article he is interested in */
	    checkcount = 0;
	    checkpoint_rc();	/* update .newsrc */
	}
	collect_subjects();		/* loads subject cache until */
					/* input is pending */
	mode = 'p';
	getcmd(buf);
	if (errno) {
	    if (LINES < 100 && !int_count)
		*buf = '\f';/* on CONT fake up refresh */
	    else {
		*buf = 'q';	/* on INTR or paper just quit */
	    }
	}
	carriage_return();
#ifndef CLEAREOL
	erase_eol();	/* and erase the prompt */
#else
	if (erase_screen && can_home_clear)	/* PWP was here */
	    clear_rest();
	else
	    erase_eol();	/* and erase the prompt */
#endif CLEAREOL
	fflush(stdout);

    fake_command:		/* used by innersearch */

	/* parse and process pager command */

	switch (page_switch()) {
	case PS_ASK:	/* reprompt "--MORE--..." */
	    goto reask_pager;
	case PS_RAISE:	/* reparse on article level */
	    mode = oldmode;
	    return DA_RAISE;
	case PS_TOEND:	/* fast pager loop exit */
	    mode = oldmode;
	    return DA_TOEND;
	case PS_NORM:	/* display more article */
	    break;
	}
    } /* end of page loop */
}

/* process pager commands */

int
page_switch()
{
    register char *s;
    
    switch (*buf) {
    case 'd':
    case Ctl('d'):	/* half page */
	special = TRUE;
	slines = LINES / 2 + 1;
	if (marking && *blinebeg != '\f') {
	    up_line();
	    highlight = --artline;
	    restart = blinebeg;
	    artpos = alinebeg;
	}
	return PS_NORM;
    case '!':			/* shell escape */
	escapade();
	return PS_ASK;
#ifdef INNERSEARCH
    case Ctl('i'):
	gline = 3;
	sprintf(cmd_buf,"^[^%c]",*blinebeg);
	compile(&gcompex,cmd_buf,TRUE,TRUE);
	goto caseG;
    case Ctl('g'):
	gline = 3;
	compile(&gcompex,"^Subject:",TRUE,TRUE);
	goto caseG;
    case 'g':		/* in-article search */
	if (!finish_command(FALSE))/* get rest of command */
	    return PS_ASK;
	s = buf+1;
	if (isspace(*s))
	    s++;
	if ((s = compile(&gcompex,s,TRUE,TRUE)) != Nullch) {
			    /* compile regular expression */
	    printf("\n%s\n",s) FLUSH;
	    return PS_ASK;
	}
	carriage_return();
	erase_eol();	/* erase the prompt */
	/* FALL THROUGH */
    caseG:
    case 'G': {
	/* ART_LINE lines_to_skip = 0; */
	ART_POS start_where;

	if (gline < 0 || gline > LINES-2)
	    gline = LINES-2;
#ifdef DEBUGGING
	if (debug & DEB_INNERSRCH)
	    printf("Start here? %d  >=? %d\n",topline + gline + 1,artline)
	      FLUSH;
#endif
	if (*buf == Ctl('i') || topline+gline+1 >= artline)
	    start_where = artpos;
			/* in case we had a line wrap */
	else {
	    start_where = vrdary(topline+gline+1);
	    if (start_where < 0)
		start_where = -start_where;
	}
	if (start_where < htype[PAST_HEADER].ht_minpos)
	    start_where = htype[PAST_HEADER].ht_minpos;
	fseek(artfp,(long)start_where,0);
	innersearch = 0; /* assume not found */
	while (fgets(buf, sizeof buf, artfp) != Nullch) {
	    /* lines_to_skip++; 		NOT USED NOW */
#ifdef DEBUGGING
	    if (debug & DEB_INNERSRCH)
		printf("Test %s",buf) FLUSH;
#endif
	    if (execute(&gcompex,buf) != Nullch) {
		innersearch = ftell(artfp);
		break;
	    }
	}
	if (!innersearch) {
	    fseek(artfp,artpos,0);
	    fputs("(Not found)",stdout) FLUSH;
	    return PS_ASK;
	}
#ifdef DEBUGGING
	if (debug & DEB_INNERSRCH)
	    printf("On page? %ld <=? %ld\n",(long)innersearch,(long)artpos)
	      FLUSH;
#endif
	if (innersearch <= artpos) {	/* already on page? */
	    if (innersearch < artpos) {
		artline = topline+1;
		while (vrdary(artline) < innersearch)
		    artline++;
	    }
	    highlight = artline - 1;
#ifdef DEBUGGING
	    if (debug & DEB_INNERSRCH)
		printf("@ %d\n",highlight) FLUSH;
#endif
	    topline = highlight - gline;
	    if (topline < -1)
		topline = -1;
	    *buf = '\f';		/* fake up a refresh */
	    innersearch = 0;
	    return page_switch();
	}
	else {				/* who knows how many lines it is? */
	    do_fseek = TRUE;
	    hide_everything = TRUE;
	}
	return PS_NORM;
    }
#else
    case 'g': case 'G': case Ctl('g'):
	notincl("g");
	return PS_ASK;
#endif
    case '\n':		/* one line */
	special = TRUE;
	slines = 2;
	return PS_NORM;
#ifdef ROTATION
    case 'X':
	rotate = !rotate;
	/* FALL THROUGH */
#endif
    case 'l':
    case '\f':		/* refresh screen */
#ifdef DEBUGGING
	if (debug & DEB_INNERSRCH) {
	    printf("Topline = %d",topline) FLUSH;
	    gets(buf);
	}
#endif
	clear();
	do_fseek = TRUE;
	artline = topline;
	if (artline < 0)
	    artline = 0;
	firstpage = (topline < 0);
	return PS_NORM;
    case 'b':
    case '\b':			/* I like backspace for this -- PWP */
					/* Leaving it undocumented in case */
					/* I want to steal the key--LAW */
    case Ctl('b'): {	/* back up a page */
	ART_LINE target;

#ifndef CLEAREOL
	clear();
#else
	if (can_home_clear)	/* if we can home do it -- PWP */
	    home_cursor();
	else
	    clear();

#endif CLEAREOL
	do_fseek = TRUE;	/* reposition article file */
	target = topline - (LINES - 2);
	artline = topline;
	do {
	    artline--;
	} while (artline >= 0 && artline > target &&
	    vrdary(artline-1) >= 0);
	topline = artline;
			/* remember top line of screen */
			/*  (line # within article file) */
	if (artline < 0)
	    artline = 0;
	firstpage = (topline < 0);
	return PS_NORM;
    }
    case 'h': {		/* help */
	int cmd;

	if ((cmd = help_page()) > 0)
	    pushchar(cmd);
	return PS_ASK;
    }
    case '\177':
    case '\0':		/* treat del,break as 'n' */
	*buf = 'n';
	/* FALL THROUGH */
    case 'k':	case 'K':
    case 'n':	case 'N':	case Ctl('n'):
    case 's':	case 'S':
    case 'u':
    case 'w':	case 'W':
    case '|':
	mark_as_read(art);	/* mark article as read */
	/* FALL THROUGH */
    case '#':
    case '$':
    case '&':
    case '-':
    case '.':
    case '/':
    case '1': case '2': case '3': case '4': case '5':
    case '6': case '7': case '8': case '9':
    case '=':
    case '?':
    case 'c':	case 'C':	
    case 'f':	case 'F':	
    case 'j':
				case Ctl('k'):
    case 'm':	case 'M':	
    case 'p':	case 'P':	case Ctl('p'):	
		case 'Q':
    case 'r':	case 'R':	case Ctl('r'):
    case 'v':
		case 'Y':
#ifndef ROTATION
    case 'x':	case 'X':
#endif
    case Ctl('x'):
    case '^':

#ifdef ROTATION
	rotate = FALSE;
#endif
	reread = FALSE;
	do_hiding = TRUE;
	if (index("nNpP",*buf) == Nullch &&
	  index("wWsS!&|/?123456789.",*buf) != Nullch) {
	    setdfltcmd();
	    standout();		/* enter standout mode */
	    printf(prompt,mailcall,dfltcmd);
			    /* print prompt, whatever it is */
	    un_standout();	/* leave standout mode */
	    putchar(' ');
	    fflush(stdout);
	}
	return PS_RAISE;	/* and pretend we were at end */
#ifdef ROTATION
    case 'x':
	rotate = TRUE;
	/* FALL THROUGH */
#endif
    case 'y':
    case Ctl('v'):		/* I like emacs -- PWP */
					/* Leaving it undocumented in case */
					/* I want to steal the key--LAW */
    case ' ':	/* continue current article */
	if (erase_screen) {	/* -e? */
#ifndef CLEAREOL
	    clear();		/* clear screen */
#else
	    if (can_home_clear)	/* if we can home do it -- PWP */
		home_cursor();
	    else
		clear();	/* else clear screen */

#endif CLEAREOL
	    if (*blinebeg != '\f') {
		restart = blinebeg;
		artline--;	 /* restart this line */
		artpos = alinebeg;
		if (marking)	/* and mark repeated line */
		    highlight = artline;
	    }
	    topline = artline;
			/* and remember top line of screen */
			/*  (line # within article file) */
	}
	else if (marking && *blinebeg != '\f') {
				/* are we marking repeats? */
	    up_line();		/* go up one line */
	    highlight = --artline;/* and get ready to highlight */
	    restart = blinebeg;	/*   the old line */
	    artpos = alinebeg;
	}
	return PS_NORM;
    case 'q':	/* quit this article? */
	do_hiding = TRUE;
	return PS_TOEND;
    default:
	fputs(hforhelp,stdout) FLUSH;
	settle_down();
	return PS_ASK;
    }
}

#ifdef INNERSEARCH
bool
innermore()
{
    if (artpos < innersearch) {		/* not even on page yet? */
#ifdef DEBUGGING
	if (debug & DEB_INNERSRCH)
	    printf("Not on page %ld < %ld\n",(long)artpos,(long)innersearch)
	      FLUSH;
#endif
	return TRUE;
    }
    if (artpos == innersearch) {	/* just got onto page? */
	isrchline = artline;		/* remember first line after */
	highlight = artline - 1;
#ifdef DEBUGGING
	if (debug & DEB_INNERSRCH)
	    printf("There it is %ld = %ld, %d @ %d\n",(long)artpos,
		(long)innersearch,hide_everything,highlight) FLUSH;
#endif
	if (hide_everything) {		/* forced refresh? */
	    topline = highlight - gline;
	    if (topline < -1)
		topline = -1;
	    return FALSE;		/* let refresh do it all */
	}
    }
#ifdef DEBUGGING
    if (debug & DEB_INNERSRCH)
	printf("Not far enough? %d <? %d + %d\n",artline,isrchline,gline)
	  FLUSH;
#endif
    if (artline < isrchline + gline) {
	return TRUE;
    }
    return FALSE;
}
#endif
!STUFFY!FUNK!
echo Extracting search.c
cat >search.c <<'!STUFFY!FUNK!'
/* $Header: search.c,v 4.3 85/05/01 11:50:16 lwall Exp $
 *
 * $Log:	search.c,v $
 * Revision 4.3  85/05/01  11:50:16  lwall
 * Baseline for release with 4.3bsd.
 * 
 */

/* string search routines */
 
/*		Copyright (c) 1981,1980 James Gosling		*/
 
/* Modified Aug. 12, 1981 by Tom London to include regular expressions
   as in ed.  RE stuff hacked over by jag to correct a few major problems,
   mainly dealing with searching within the buffer rather than copying
   each line to a separate array.  Newlines can now appear in RE's */

/* Ripped to shreds and glued back together to make a search package,
 * July 6, 1984, by Larry Wall. (If it doesn't work, it's probably my fault.)
 * Changes include:
 *	Buffer, window, and mlisp stuff gone.
 *	Translation tables reduced to 1 table.
 *	Expression buffer is now dynamically allocated.
 *	Character classes now implemented with a bitmap.
 */

#include "EXTERN.h"
#include "common.h"
#include "util.h"
#include "INTERN.h"
#include "search.h"

#ifndef BITSPERBYTE
#define BITSPERBYTE 8
#endif

#define BMAPSIZ (127 / BITSPERBYTE + 1)

/* meta characters in the "compiled" form of a regular expression */
#define	CBRA	2		/* \( -- begin bracket */
#define	CCHR	4		/* a vanilla character */
#define	CDOT	6		/* . -- match anything except a newline */
#define	CCL	8		/* [...] -- character class */
#define	NCCL	10		/* [^...] -- negated character class */
#define	CDOL	12		/* $ -- matches the end of a line */
#define	CEND	14		/* The end of the pattern */
#define	CKET	16		/* \) -- close bracket */
#define	CBACK	18		/* \N -- backreference to the Nth bracketed
				   string */
#define CIRC	20		/* ^ matches the beginning of a line */

#define WORD	32		/* matches word character \w */
#define NWORD	34		/* matches non-word characer \W */
#define WBOUND	36		/* matches word boundary \b */
#define NWBOUND	38		/* matches non-(word boundary) \B */
 
#define	STAR	01		/* * -- Kleene star, repeats the previous
				   REas many times as possible; the value
				   ORs with the other operator types */
 
#define ASCSIZ 0200
typedef char	TRANSTABLE[ASCSIZ];

static	TRANSTABLE trans = {
0000,0001,0002,0003,0004,0005,0006,0007,
0010,0011,0012,0013,0014,0015,0016,0017,
0020,0021,0022,0023,0024,0025,0026,0027,
0030,0031,0032,0033,0034,0035,0036,0037,
0040,0041,0042,0043,0044,0045,0046,0047,
0050,0051,0052,0053,0054,0055,0056,0057,
0060,0061,0062,0063,0064,0065,0066,0067,
0070,0071,0072,0073,0074,0075,0076,0077,
0100,0101,0102,0103,0104,0105,0106,0107,
0110,0111,0112,0113,0114,0115,0116,0117,
0120,0121,0122,0123,0124,0125,0126,0127,
0130,0131,0132,0133,0134,0135,0136,0137,
0140,0141,0142,0143,0144,0145,0146,0147,
0150,0151,0152,0153,0154,0155,0156,0157,
0160,0161,0162,0163,0164,0165,0166,0167,
0170,0171,0172,0173,0174,0175,0176,0177,
};
static bool folding = FALSE;

static int err;
static char *FirstCharacter;

void
search_init()
{
#ifdef UNDEF
    register int    i;
    
    for (i = 0; i < ASCSIZ; i++)
	trans[i] = i;
#else
    ;
#endif
}

void
init_compex(compex)
register COMPEX *compex;
{
    /* the following must start off zeroed */

    compex->eblen = 0;
    compex->brastr = Nullch;
}

void
free_compex(compex)
register COMPEX *compex;
{
    if (compex->eblen) {
	free(compex->expbuf);
	compex->eblen = 0;
    }
    if (compex->brastr) {
	free(compex->brastr);
	compex->brastr = Nullch;
    }
}

static char *gbr_str = Nullch;
static int gbr_siz = 0;

char *
getbracket(compex,n)
register COMPEX *compex;
int n;
{
    int length = compex->braelist[n] - compex->braslist[n];

    if (!compex->nbra || n > compex->nbra || !compex->braelist[n] || length<0)
	return nullstr;
    growstr(&gbr_str, &gbr_siz, length+1);
    safecpy(gbr_str, compex->braslist[n], length+1);
    return gbr_str;
}

void
case_fold(which)
int which;
{
    register int i;

    if (which != folding) {
	if (which) {
	    for (i = 'A'; i <= 'Z'; i++)
		trans[i] = tolower(i);
	}
	else {
	    for (i = 'A'; i <= 'Z'; i++)
		trans[i] = i;
	}
	folding = which;
    }
}

/* Compile the given regular expression into a [secret] internal format */

char *
compile (compex, strp, RE, fold)
register COMPEX *compex;
register char   *strp;
int RE;
int fold;
{
    register int c;
    register char  *ep;
    char   *lastep;
    char    bracket[NBRA],
	   *bracketp;
    char **alt = compex->alternatives;
    char *retmes = "Badly formed search string";
 
    case_fold(compex->do_folding = fold);
    if (!compex->eblen) {
	compex->expbuf = safemalloc(84);
	compex->eblen = 80;
    }
    ep = compex->expbuf;		/* point at expression buffer */
    *alt++ = ep;			/* first alternative starts here */
    bracketp = bracket;			/* first bracket goes here */
    if (*strp == 0) {			/* nothing to compile? */
	if (*ep == 0)			/* nothing there yet? */
	    return "Null search string";
	return Nullch;			/* just keep old expression */
    }
    compex->nbra = 0;			/* no brackets yet */
    lastep = 0;
    for (;;) {
	if (ep - compex->expbuf >= compex->eblen)
	    grow_eb(compex);
	c = *strp++;			/* fetch next char of pattern */
	if (c == 0) {			/* end of pattern? */
	    if (bracketp != bracket) {	/* balanced brackets? */
#ifdef VERBOSE
		retmes = "Unbalanced parens";
#endif
		goto cerror;
	    }
	    *ep++ = CEND;		/* terminate expression */
	    *alt++ = 0;			/* terminal alternative list */
	    /*
	    compex->eblen = ep - compex->expbuf + 1;
	    compex->expbuf = saferealloc(compex->expbuf,compex->eblen+4); */
	    return Nullch;		/* return success */
	}
	if (c != '*')
	    lastep = ep;
	if (!RE) {			/* just a normal search string? */
	    *ep++ = CCHR;		/* everything is a normal char */
	    *ep++ = c;
	}
	else				/* it is a regular expression */
	    switch (c) {
 
		case '\\':		/* meta something */
		    switch (c = *strp++) {
		    case '(':
			if (compex->nbra >= NBRA) {
#ifdef VERBOSE
			    retmes = "Too many parens";
#endif
			    goto cerror;
			}
			*bracketp++ = ++compex->nbra;
			*ep++ = CBRA;
			*ep++ = compex->nbra;
			break;
		    case '|':
			if (bracketp>bracket) {
#ifdef VERBOSE
			    retmes = "No \\| in parens";	/* Alas! */
#endif
			    goto cerror;
			}
			*ep++ = CEND;
			*alt++ = ep;
			break;
		    case ')':
			if (bracketp <= bracket) {
#ifdef VERBOSE
			    retmes = "Unmatched right paren";
#endif
			    goto cerror;
			}
			*ep++ = CKET;
			*ep++ = *--bracketp;
			break;
		    case 'w':
			*ep++ = WORD;
			break;
		    case 'W':
			*ep++ = NWORD;
			break;
		    case 'b':
			*ep++ = WBOUND;
			break;
		    case 'B':
			*ep++ = NWBOUND;
			break;
		    case '0': case '1': case '2': case '3': case '4':
		    case '5': case '6': case '7': case '8': case '9':
			*ep++ = CBACK;
			*ep++ = c - '0';
			break;
		    default:
			*ep++ = CCHR;
			if (c == '\0')
			    goto cerror;
			*ep++ = c;
			break;
		    }
		    break;
		case '.':
		    *ep++ = CDOT;
		    continue;
 
		case '*':
		    if (lastep == 0 || *lastep == CBRA || *lastep == CKET
			|| *lastep == CIRC
			|| (*lastep&STAR)|| *lastep>NWORD)
			goto defchar;
		    *lastep |= STAR;
		    continue;
 
		case '^':
		    if (ep != compex->expbuf && ep[-1] != CEND)
			goto defchar;
		    *ep++ = CIRC;
		    continue;
 
		case '$':
		    if (*strp != 0 && (*strp != '\\' || strp[1] != '|'))
			goto defchar;
		    *ep++ = CDOL;
		    continue;
 
		case '[': {		/* character class */
		    register int i;
		    
		    if (ep - compex->expbuf >= compex->eblen - BMAPSIZ)
			grow_eb(compex);	/* reserve bitmap */
		    for (i = BMAPSIZ; i; --i)
			ep[i] = 0;
		    
		    if ((c = *strp++) == '^') {
			c = *strp++;
			*ep++ = NCCL;	/* negated */
		    }
		    else
			*ep++ = CCL;	/* normal */
		    
		    i = 0;		/* remember oldchar */
		    do {
			if (c == '\0') {
#ifdef VERBOSE
			    retmes = "Missing ]";
#endif
			    goto cerror;
			}
			if (*strp == '-' && *(++strp))
			    i = *strp++;
			else
			    i = c;
			while (c <= i) {
			    ep[c / BITSPERBYTE] |= 1 << (c % BITSPERBYTE);
			    if (fold && isalpha(c))
				ep[(c ^ 32) / BITSPERBYTE] |=
				    1 << ((c ^ 32) % BITSPERBYTE);
					/* set the other bit too */
			    c++;
			}
		    } while ((c = *strp++) != ']');
		    ep += BMAPSIZ;
		    continue;
		}
 
	    defchar:
		default:
		    *ep++ = CCHR;
		    *ep++ = c;
	    }
    }
cerror:
    compex->expbuf[0] = 0;
    compex->nbra = 0;
    return retmes;
}

void
grow_eb(compex)
register COMPEX *compex;
{
    compex->eblen += 80;
    compex->expbuf = saferealloc(compex->expbuf, (MEM_SIZE)compex->eblen + 4);
}

char *
execute (compex, addr)
register COMPEX *compex;
char *addr;
{
    register char *p1 = addr;
    register char *trt = trans;
    register int c;
 
    if (addr == Nullch)
	return Nullch;
    if (compex->nbra) {			/* any brackets? */
	for (c = 0; c <= compex->nbra; c++)
	    compex->braslist[c] = compex->braelist[c] = Nullch;
	if (compex->brastr)
	    free(compex->brastr);
	compex->brastr = savestr(p1);	/* in case p1 is not static */
	p1 = compex->brastr;		/* ! */
    }
    case_fold(compex->do_folding);	/* make sure table is correct */
    FirstCharacter = p1;		/* for ^ tests */
    if (compex->expbuf[0] == CCHR && !compex->alternatives[1]) {
	c = trt[compex->expbuf[1]];	/* fast check for first character */
	do {
	    if (trt[*p1] == c && advance (compex, p1, compex->expbuf))
		return p1;
	    p1++;
	} while (*p1 && !err);
	return Nullch;
    }
    else {			/* regular algorithm */
	do {
	    register char **alt = compex->alternatives;
	    while (*alt) {
		if (advance (compex, p1, *alt++))
		    return p1;
	    }
	    p1++;
	} while (*p1 && !err);
	return Nullch;
    }
}
 
/* advance the match of the regular expression starting at ep along the
   string lp, simulates an NDFSA */
bool
advance (compex, lp, ep)
register COMPEX *compex;
register char *ep;
register char *lp;
{
    register char *curlp;
    register char *trt = trans;
    register int i;
 
    while ((*ep & STAR) || *lp || *ep == CIRC || *ep == CKET)
	switch (*ep++) {
 
	    case CCHR:
		if (trt[*ep++] != trt[*lp]) return FALSE;
		lp++;
		continue;
 
	    case CDOT:
		if (*lp == '\n') return FALSE;
		lp++;
		continue;
 
	    case CDOL:
		if (!*lp || *lp == '\n')
		    continue;
		return FALSE;
 
	    case CIRC:
		if (lp == FirstCharacter || lp[-1]=='\n')
		    continue;
		return FALSE;
 
	    case WORD:
		if (isalnum(*lp)) {
		    lp++;
		    continue;
		}
		return FALSE;
 
	    case NWORD:
		if (!isalnum(*lp)) {
		    lp++;
		    continue;
		}
		return FALSE;
 
	    case WBOUND:
		if ((lp == FirstCharacter || !isalnum(lp[-1])) !=
			(!*lp || !isalnum(*lp)) )
		    continue;
		return FALSE;
 
	    case NWBOUND:
		if ((lp == FirstCharacter || !isalnum(lp[-1])) ==
			(!*lp || !isalnum(*lp)))
		    continue;
		return FALSE;
 
	    case CEND:
		return TRUE;
 
	    case CCL:
		if (cclass (ep, *lp, 1)) {
		    ep += BMAPSIZ;
		    lp++;
		    continue;
		}
		return FALSE;
 
	    case NCCL:
		if (cclass (ep, *lp, 0)) {
		    ep += BMAPSIZ;
		    lp++;
		    continue;
		}
		return FALSE;
 
	    case CBRA:
		compex->braslist[*ep++] = lp;
		continue;
 
	    case CKET:
		i = *ep++;
		compex->braelist[i] = lp;
		compex->braelist[0] = lp;
		compex->braslist[0] = compex->braslist[i];
		continue;
 
	    case CBACK:
		if (compex->braelist[i = *ep++] == 0) {
		    fputs("bad braces\n",stdout) FLUSH;
		    err = TRUE;
		    return FALSE;
		}
		if (backref (compex, i, lp)) {
		    lp += compex->braelist[i] - compex->braslist[i];
		    continue;
		}
		return FALSE;
 
	    case CBACK | STAR:
		if (compex->braelist[i = *ep++] == 0) {
		    fputs("bad braces\n",stdout) FLUSH;
		    err = TRUE;
		    return FALSE;
		}
		curlp = lp;
		while (backref (compex, i, lp)) {
		    lp += compex->braelist[i] - compex->braslist[i];
		}
		while (lp >= curlp) {
		    if (advance (compex, lp, ep))
			return TRUE;
		    lp -= compex->braelist[i] - compex->braslist[i];
		}
		continue;
 
	    case CDOT | STAR:
		curlp = lp;
		while (*lp++ && lp[-1] != '\n');
		goto star;
 
	    case WORD | STAR:
		curlp = lp;
		while (*lp++ && isalnum(lp[-1]));
		goto star;
 
	    case NWORD | STAR:
		curlp = lp;
		while (*lp++ && !isalnum(lp[-1]));
		goto star;
 
	    case CCHR | STAR:
		curlp = lp;
		while (*lp++ && trt[lp[-1]] == trt[*ep]);
		ep++;
		goto star;
 
	    case CCL | STAR:
	    case NCCL | STAR:
		curlp = lp;
		while (*lp++ && cclass (ep, lp[-1], ep[-1] == (CCL | STAR)));
		ep += BMAPSIZ;
		goto star;
 
	star:
		do {
		    lp--;
		    if (advance (compex, lp, ep))
			return TRUE;
		} while (lp > curlp);
		return FALSE;
 
	    default:
		fputs("Badly compiled pattern\n",stdout) FLUSH;
		err = TRUE;
		return -1;
	}
	if (*ep == CEND || *ep == CDOL) {
	    return TRUE;
    }
    return FALSE;
}
 
bool
backref (compex, i, lp)
register COMPEX *compex;
register int i;
register char *lp;
{
    register char *bp;
 
    bp = compex->braslist[i];
    while (*lp && *bp == *lp) {
	bp++;
	lp++;
	if (bp >= compex->braelist[i])
	    return TRUE;
    }
    return FALSE;
}

bool
cclass (set, c, af)
register char  *set;
register int c;
{
    c &= 0177;
#if BITSPERBYTE == 8
    if (set[c >> 3] & 1 << (c & 7))
#else
    if (set[c / BITSPERBYTE] & 1 << (c % BITSPERBYTE))
#endif
	return af;
    return !af;
}
!STUFFY!FUNK!
echo Extracting ngstuff.c
cat >ngstuff.c <<'!STUFFY!FUNK!'
/* $Header: ngstuff.c,v 4.3 85/05/01 11:45:03 lwall Exp $
 *
 * $Log:	ngstuff.c,v $
 * Revision 4.3  85/05/01  11:45:03  lwall
 * Baseline for release with 4.3bsd.
 * 
 */

#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) FLUSH;
	    sig_catcher(0);
	}
    }
    while (*s == ' ') s++;
					/* skip leading spaces */
    interp(cmd_buf, (sizeof 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) FLUSH;
	    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();
#ifdef PUSHBACK
    else if (buf[1] == '&') {
	if (!buf[2]) {
	    page_init();
	    show_macros();
	}
	else {
	    char tmpbuf[LBUFLEN];
	    register char *s;

	    for (s=buf+2; isspace(*s); s++);
	    mac_line(s,tmpbuf,(sizeof tmpbuf));
	}
    }
#endif
    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) FLUSH;
		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;
	if (lastart < 1) {
	    fputs("\nNo articles\n",stdout) FLUSH;
	    return NN_ASK;
	}
#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) FLUSH;
	    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) FLUSH;
	    pad(just_a_sec/3);
	}
	if (max < min) {
	    fputs("\nBad range\n",stdout) FLUSH;
	    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)
		      FLUSH;
		ELSE
#endif
#ifdef TERSE
		    printf("\n(Intr at %ld)\n",(long)art) FLUSH;
#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') FLUSH;		/* 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, (sizeof 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') FLUSH;
	ELSE
#endif
#ifdef TERSE
	    putchar(' ');
#endif
    }
    return 0;
}

!STUFFY!FUNK!
echo Extracting makedist
cat >makedist <<'!STUFFY!FUNK!'
#!/bin/sh
# $Header: makedist,v 4.3 85/05/01 11:42:35 lwall Exp $
#
# $Log:	makedist,v $
# Revision 4.3  85/05/01  11:42:35  lwall
# Baseline for release with 4.3bsd.
# 

rm -f kit*.list
manifake
kitlists
manimake
makekit kit*.list
!STUFFY!FUNK!
echo ""
echo "End of kit 4 (of 9)"
cat /dev/null >kit4isdone
config=true
for iskit in 1 2 3 4 5 6 7 8 9; 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



More information about the Mod.sources mailing list