rn version 4.3 (kit 6 of 9)

sources-request at genrad.UUCP sources-request at genrad.UUCP
Sat May 11 21:56:57 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 6 (of 9).  If kit 6 is complete, the line"
echo '"'"End of kit 6 (of 9)"'" will echo at the end.'
echo ""
export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
echo Extracting util.c
cat >util.c <<'!STUFFY!FUNK!'
/* $Header: util.c,v 4.3 85/05/01 11:51:44 lwall Exp $
 *
 * $Log:	util.c,v $
 * Revision 4.3  85/05/01  11:51:44  lwall
 * Baseline for release with 4.3bsd.
 * 
 */

#include "EXTERN.h"
#include "common.h"
#include "final.h"
#include "ndir.h"
#include "INTERN.h"
#include "util.h"

void
util_init()
{
    ;
}
    
/* fork and exec a shell command */

int
doshell(shl,s)
char *s, *shl;
{
    int status, pid, w;
    register int (*istat)(), (*qstat)();
    int (*signal())();
    char *shell;

#ifdef SIGTSTP
    sigset(SIGTSTP,SIG_DFL);
    sigset(SIGCONT,SIG_DFL);
#endif
    if (shl != Nullch)
	shell = shl;
    else if ((shell = getenv("SHELL")) == Nullch || !*shell)
	shell = PREFSHELL;
    if ((pid = vfork()) == 0) {
	if (*s)
	    execl(shell, shell, "-c", s, 0);
	else
	    execl(shell, shell, Nullch, Nullch, 0);
	_exit(127);
    }
#ifndef lint
    istat = signal(SIGINT, SIG_IGN);
    qstat = signal(SIGQUIT, SIG_IGN);
#else
    istat = Null(int (*)());
    qstat = Null(int (*)());
#endif lint
    waiting = TRUE;
    while ((w = wait(&status)) != pid && w != -1)
	;
    if (w == -1)
	status = -1;
    waiting = FALSE;
    signal(SIGINT, istat);
    signal(SIGQUIT, qstat);
#ifdef SIGTSTP
    sigset(SIGTSTP,stop_catcher);
    sigset(SIGCONT,cont_catcher);
#endif
    return status;
}

static char nomem[] = "rn: out of memory!\n";

/* paranoid version of malloc */

char *
safemalloc(size)
MEM_SIZE size;
{
    char *ptr;
    char *malloc();

    ptr = malloc(size?size:1);	/* malloc(0) is NASTY on our system */
    if (ptr != Nullch)
	return ptr;
    else {
	fputs(nomem,stdout) FLUSH;
	sig_catcher(0);
    }
    /*NOTREACHED*/
}

/* paranoid version of realloc */

char *
saferealloc(where,size)
char *where;
MEM_SIZE size;
{
    char *ptr;
    char *realloc();

    ptr = realloc(where,size?size:1);	/* realloc(0) is NASTY on our system */
    if (ptr != Nullch)
	return ptr;
    else {
	fputs(nomem,stdout) FLUSH;
	sig_catcher(0);
    }
    /*NOTREACHED*/
}

/* safe version of string copy */

char *
safecpy(to,from,len)
char *to;
register char *from;
register int len;
{
    register char *dest = to;

    if (from != Nullch) 
	for (len--; len && (*dest++ = *from++); len--) ;
    *dest = '\0';
    return to;
}

/* safe version of string concatenate, with \n deletion and space padding */

char *
safecat(to,from,len)
char *to;
register char *from;
register int len;
{
    register char *dest = to;

    len--;				/* leave room for null */
    if (*dest) {
	while (len && *dest++) len--;
	if (len) {
	    len--;
	    *(dest-1) = ' ';
	}
    }
    if (from != Nullch)
	while (len && (*dest++ = *from++)) len--;
    if (len)
	dest--;
    if (*(dest-1) == '\n')
	dest--;
    *dest = '\0';
    return to;
}

/* copy a string up to some (non-backslashed) delimiter, if any */

char *
cpytill(to,from,delim)
register char *to, *from;
register int delim;
{
    for (; *from; from++,to++) {
	if (*from == '\\' && from[1] == delim)
	    from++;
	else if (*from == delim)
	    break;
	*to = *from;
    }
    *to = '\0';
    return from;
}

/* return ptr to little string in big string, NULL if not found */

char *
instr(big, little)
char *big, *little;

{
    register char *t, *s, *x;

    for (t = big; *t; t++) {
	for (x=t,s=little; *s; x++,s++) {
	    if (!*x)
		return Nullch;
	    if (*s != *x)
		break;
	}
	if (!*s)
	    return t;
    }
    return Nullch;
}

/* effective access */

#ifdef SETUIDGID
int
eaccess(filename, mod)
char *filename;
int mod;
{
    int protection, euid;
    
    mod &= 7;				/* remove extraneous garbage */
    if (stat(filename, &filestat) < 0)
	return -1;
    euid = geteuid();
    if (euid == ROOTID)
	return 0;
    protection = 7 & (filestat.st_mode >>
      (filestat.st_uid == euid ? 6 :
        (filestat.st_gid == getegid() ? 3 : 0)
      ));
    if ((mod & protection) == mod)
	return 0;
    errno = EACCES;
    return -1;
}
#endif

/*
 * Get working directory
 */

#ifdef GETWD
#define	dot	"."
#define	dotdot	".."

static	char	*name;

static	DIR	*dirp;
static	int	off;
static	struct	stat	d, dd;
static	struct	direct	*dir;

char *
getwd(np)
char *np;
{
	long rdev, rino;

	*np++ = '/';
	*np = 0;
	name = np;
	off = -1;
	stat("/", &d);
	rdev = d.st_dev;
	rino = d.st_ino;
	for (;;) {
		stat(dot, &d);
		if (d.st_ino==rino && d.st_dev==rdev)
			goto done;
		if ((dirp = opendir(dotdot)) == Null(DIR *))
			prexit("getwd: cannot open ..\n");
		stat(dotdot, &dd);
		chdir(dotdot);
		if(d.st_dev == dd.st_dev) {
			if(d.st_ino == dd.st_ino)
				goto done;
			do
				if ((dir = readdir(dirp)) == Null(struct direct *))
					prexit("getwd: read error in ..\n");
			while (dir->d_ino != d.st_ino);
		}
		else do {
				if ((dir = readdir(dirp)) == Null(struct direct *))
					prexit("getwd: read error in ..\n");
				stat(dir->d_name, &dd);
			} while(dd.st_ino != d.st_ino || dd.st_dev != d.st_dev);
		cat();
		closedir(dirp);
	}
done:
	name--;
	if (chdir(name) < 0) {
		printf("getwd: can't cd back to %s\n",name) FLUSH;
		sig_catcher(0);
	}
	return (name);
}

void
cat()
{
	register i, j;

	i = -1;
	while (dir->d_name[++i] != 0);
	if ((off+i+2) > 1024-1)
		return;
	for(j=off+1; j>=0; --j)
		name[j+i+1] = name[j];
	if (off >= 0)
		name[i] = '/';
	off=i+off+1;
	name[off] = 0;
	for(--i; i>=0; --i)
		name[i] = dir->d_name[i];
}

void
prexit(cp)
char *cp;
{
	write(2, cp, strlen(cp));
	sig_catcher(0);
}
#else
char *
getwd(np)			/* shorter but slower */
char *np;
{
    FILE *popen();
    FILE *pipefp = popen("/bin/pwd","r");

    if (pipefd == Nullfp) {
	printf("Can't run /bin/pwd\n") FLUSH;
	finalize(1);
    }
    fgets(np,512,pipefp);
    np[strlen(np)-1] = '\0';	/* wipe out newline */
    pclose(pipefp);
    return np;
}
#endif

/* just like fgets but will make bigger buffer as necessary */

char *
get_a_line(original_buffer,buffer_length,fp)
char *original_buffer;
register int buffer_length;
FILE *fp;
{
    register int bufix = 0;
    register int nextch;
    register char *some_buffer_or_other = original_buffer;

    do {
	if (bufix >= buffer_length) {
	    buffer_length *= 2;
	    if (some_buffer_or_other == original_buffer) {
					/* currently static? */
		some_buffer_or_other = safemalloc((MEM_SIZE)buffer_length+1);
		strncpy(some_buffer_or_other,original_buffer,buffer_length/2);
					/* so we must copy it */
	    }
	    else {			/* just grow in place, if possible */
		some_buffer_or_other = saferealloc(some_buffer_or_other,
		    (MEM_SIZE)buffer_length+1);
	    }
	}
	if ((nextch = getc(fp)) == EOF)
	    return Nullch;
	some_buffer_or_other[bufix++] = (char) nextch;
    } while (nextch && nextch != '\n');
    some_buffer_or_other[bufix] = '\0';
    len_last_line_got = bufix;
    return some_buffer_or_other;
}

/* copy a string to a safe spot */

char *
savestr(str)
char *str;
{
    register char *newaddr = safemalloc((MEM_SIZE)(strlen(str)+1));

    strcpy(newaddr,str);
    return newaddr;
}

int
makedir(dirname,nametype)
register char *dirname;
int nametype;
{
#ifdef MAKEDIR
    register char *end;
    register char *s;
    char tmpbuf[1024];
    register char *tbptr = tmpbuf+5;

    for (end = dirname; *end; end++) ;	/* find the end */
    if (nametype == MD_FILE) {		/* not to create last component? */
	for (--end; end != dirname && *end != '/'; --end) ;
	if (*end != '/')
	    return 0;			/* nothing to make */
	*end = '\0';			/* isolate file name */
    }
    strcpy(tmpbuf,"mkdir");

    s = end;
    for (;;) {
	if (stat(dirname,&filestat) >= 0) {
					/* does this much exist? */
	    *s = '/';			/* mark this as existing */
	    break;
	}
	s = rindex(dirname,'/');	/* shorten name */
	if (!s)				/* relative path! */
	    break;			/* hope they know what they are doing */
	*s = '\0';			/* mark as not existing */
    }
    
    for (s=dirname; s <= end; s++) {	/* this is grody but efficient */
	if (!*s) {			/* something to make? */
	    sprintf(tbptr," %s",dirname);
	    tbptr += strlen(tbptr);	/* make it, sort of */
	    *s = '/';			/* mark it made */
	}
    }
    if (nametype == MD_DIR)		/* don't need final slash unless */
	*end = '\0';			/*  a filename follows the dir name */

    return (tbptr==tmpbuf+5 ? 0 : doshell(sh,tmpbuf));
					/* exercise our faith */
#else
    sprintf(cmd_buf,"%s %s %d", filexp(DIRMAKER), dirname, nametype);
    return doshell(sh,cmd_buf);
#endif
}

#ifdef SETENV
static bool firstsetenv = TRUE;
extern char **environ;

void
setenv(nam,val)
char *nam, *val;
{
    register int i=envix(nam);		/* where does it go? */

    if (!environ[i]) {			/* does not exist yet */
	if (firstsetenv) {		/* need we copy environment? */
	    int j;
#ifndef lint
	    char **tmpenv = (char**)	/* point our wand at memory */
		safemalloc((MEM_SIZE) (i+2) * sizeof(char*));
#else
	    char **tmpenv = Null(char **);
#endif lint
    
	    firstsetenv = FALSE;
	    for (j=0; j<i; j++)		/* copy environment */
		tmpenv[j] = environ[j];
	    environ = tmpenv;		/* tell exec where it is now */
	}
#ifndef lint
	else
	    environ = (char**) saferealloc((char*) environ,
		(MEM_SIZE) (i+2) * sizeof(char*));
					/* just expand it a bit */
#endif lint
	environ[i+1] = Nullch;	/* make sure it's null terminated */
    }
    environ[i] = safemalloc((MEM_SIZE) strlen(nam) + strlen(val) + 2);
					/* this may or may not be in */
					/* the old environ structure */
    sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
}

int
envix(nam)
char *nam;
{
    register int i, len = strlen(nam);

    for (i = 0; environ[i]; i++) {
	if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
	    break;			/* strnEQ must come first to avoid */
    }					/* potential SEGV's */
    return i;
}
#endif

void
notincl(feature)
char *feature;
{
    printf("\nNo room for feature \"%s\" on this machine.\n",feature) FLUSH;
}

char *
getval(nam,def)
char *nam,*def;
{
    char *val;

    if ((val = getenv(nam)) == Nullch || !*val)
	val = def;
    return val;
}

/* grow a static string to at least a certain length */

void
growstr(strptr,curlen,newlen)
char **strptr;
int *curlen;
int newlen;
{
    if (newlen > *curlen) {		/* need more room? */
	if (*curlen)
	    *strptr = saferealloc(*strptr,(MEM_SIZE)newlen);
	else
	    *strptr = safemalloc((MEM_SIZE)newlen);
	*curlen = newlen;
    }
}

void
setdef(buffer,dflt)
char *buffer,*dflt;
{
#ifdef STRICTCR
    if (*buffer == ' ')
#else
    if (*buffer == ' ' || *buffer == '\n')
#endif
    {
	if (*dflt == '^' && isupper(dflt[1]))
	    *buffer = Ctl(dflt[1]);
	else
	    *buffer = *dflt;
    }
}
!STUFFY!FUNK!
echo Extracting respond.c
cat >respond.c <<'!STUFFY!FUNK!'
/* $Header: respond.c,v 4.3 85/05/01 11:47:04 lwall Exp $
 *
 * $Log:	respond.c,v $
 * Revision 4.3  85/05/01  11:47:04  lwall
 * Baseline for release with 4.3bsd.
 * 
 */

#include "EXTERN.h"
#include "common.h"
#include "intrp.h"
#include "head.h"
#include "term.h"
#include "ng.h"
#include "util.h"
#include "rn.h"
#include "intrp.h"
#include "artio.h"
#include "final.h"
#include "INTERN.h"
#include "respond.h"

static char nullart[] = "\nNull article\n";

void
respond_init()
{
    ;
}

int
save_article()
{
    bool use_pref;
    register char *s, *c;
    char altbuf[CBUFLEN];
    int iter;
    bool interactive = (buf[1] == FINISHCMD);
    
    if (!finish_command(interactive))	/* get rest of command */
	return SAVE_ABORT;
    use_pref = isupper(*buf);
#ifdef ASYNC_PARSE
    parse_maybe(art);
#endif
    savefrom = (*buf=='w' || *buf=='W' ? htype[PAST_HEADER].ht_minpos : 0);
    if (artopen(art) == Nullfp) {
#ifdef VERBOSE
	IF(verbose)
	    fputs("\n\
Saving null articles is not very productive!  :-)\n\
",stdout) FLUSH;
	ELSE
#endif
#ifdef TERSE
	    fputs(nullart,stdout) FLUSH;
#endif
	return SAVE_DONE;
    }
    if (chdir(cwd)) {
	printf(nocd,cwd) FLUSH;
	sig_catcher(0);
    }
    if (savedest)
	free(savedest);
    if ((s = index(buf,'|')) != Nullch) {
				/* is it a pipe command? */
	s++;			/* skip the | */
	while (*s == ' ') s++;
	safecpy(altbuf,filexp(s),sizeof altbuf);
	savedest = altbuf;
	interp(cmd_buf, (sizeof cmd_buf), getval("PIPESAVER",PIPESAVER));
				/* then set up for command */
	resetty();		/* restore tty state */
	if (use_pref)		/* use preferred shell? */
	    doshell(Nullch,cmd_buf);
				/* do command with it */
	else
	    doshell(sh,cmd_buf);	/* do command with sh */
	noecho();		/* and stop echoing */
	crmode();		/* and start cbreaking */
	savedest = savestr(savedest);
    }
    else {			/* normal save */
	bool there, mailbox;
	char *savename = getval("SAVENAME",SAVENAME);

	s = buf+1;		/* skip s or S */
	if (*s == '-') {	/* if they are confused, skip - also */
#ifdef VERBOSE
	    IF(verbose)
		fputs("Warning: '-' ignored.  This isn't readnews.\n",stdout)
		  FLUSH;
	    ELSE
#endif
#ifdef TERSE
		fputs("'-' ignored.\n",stdout) FLUSH;
#endif
	    s++;
	}
	for (; *s == ' '; s++);	/* skip spaces */
	safecpy(altbuf,filexp(s),sizeof altbuf);
	s = altbuf;
	if (! index(s,'/')) {
	    interp(buf, (sizeof buf), getval("SAVEDIR",SAVEDIR));
	    if (makedir(buf,MD_DIR))	/* ensure directory exists */
		strcpy(buf,cwd);
	    if (*s) {
		for (c = buf; *c; c++) ;
		*c++ = '/';
		strcpy(c,s);		/* add filename */
	    }
	    s = buf;
	}
	for (iter = 0;
	    (there = stat(s,&filestat) >= 0) &&
	    (filestat.st_mode & S_IFDIR);
	    iter++) {			/* is it a directory? */

	    c = (s+strlen(s));
	    *c++ = '/';			/* put a slash before filename */
	    interp(c, s==buf?(sizeof buf):(sizeof altbuf),
		iter ? "News" : savename );
				/* generate a default name somehow or other */
	    if (index(c,'/')) {		/* yikes, a '/' in the filename */
		makedir(s,MD_FILE);
	    }
	}
	if (*s != '/') {		/* relative path? */
	    c = (s==buf ? altbuf : buf);
	    sprintf(c, "%s/%s", cwd, s);
	    s = c;			/* absolutize it */
	}
	s = savedest = savestr(s);	/* doesn't move any more */
					/* make it handy for %b */
	if (!there) {
	    if (mbox_always)
		mailbox = TRUE;
	    else if (norm_always)
		mailbox = FALSE;
	    else {
		char *dflt = (instr(savename,"%a") ? "nyq" : "ynq");
		
		sprintf(cmd_buf,
		"\nFile %s doesn't exist--\n	use mailbox format? [%s] ",
		  s,dflt);
	      reask_save:
		in_char(cmd_buf);
		putchar('\n') FLUSH;
		setdef(cmd_buf,dflt);
#ifdef VERIFY
		printcmd();
#endif
		if (*buf == 'h') {
#ifdef VERBOSE
		    IF(verbose)
			printf("\n\
Type y to create %s as a mailbox.\n\
Type n to create it as a normal file.\n\
Type q to abort the save.\n\
",s) FLUSH;
		    ELSE
#endif
#ifdef TERSE
			fputs("\n\
y to create mailbox.\n\
n to create normal file.\n\
q to abort.\n\
",stdout) FLUSH;
#endif
		    goto reask_save;
		}
		else if (*buf == 'n') {
		    mailbox = FALSE;
		}
		else if (*buf == 'y') {
		    mailbox = TRUE;
		}
		else if (*buf == 'q') {
		    goto s_bomb;
		}
		else {
		    fputs(hforhelp,stdout) FLUSH;
		    settle_down();
		    goto reask_save;
		}
	    }
	}
	else if (filestat.st_mode & S_IFCHR)
	    mailbox = FALSE;
	else {
	    int tmpfd;
	    
	    tmpfd = open(s,0);
	    if (tmpfd == -1)
		mailbox = FALSE;
	    else {
		read(tmpfd,buf,LBUFLEN);
		c = buf;
		if (!isspace(MBOXCHAR))
		    while (isspace(*c))
			c++;
		mailbox = (*c == MBOXCHAR);
		close(tmpfd);
	    }
	}

	safecpy(cmd_buf, filexp(mailbox ?
	    getval("MBOXSAVER",MBOXSAVER) :
	    getval("NORMSAVER",NORMSAVER) ), sizeof cmd_buf);
				/* format the command */
	resetty();		/* make terminal behave */
	if (doshell(use_pref?Nullch:SH,cmd_buf))
	    fputs("Not saved",stdout);
	else
	    printf("%s to %s %s",
	      there?"Appended":"Saved",
	      mailbox?"mailbox":"file",
	      s);
	if (interactive)
	    putchar('\n') FLUSH;
	noecho();		/* make terminal do what we want */
	crmode();
    }
s_bomb:
    if (chdir(spool) || chdir(ngdir)) {
	printf(nocd,ngdir) FLUSH;
	sig_catcher(0);
    }
    return SAVE_DONE;
}

int
cancel_article()
{
    char *artid_buf;
    char *ngs_buf;
    char *from_buf;
    char *reply_buf;
    int myuid = getuid();
    int r = -1;

    if (artopen(art) == Nullfp) {
#ifdef VERBOSE
	IF(verbose)
	    fputs("\n\
Cancelling null articles is your idea of fun?  :-)\n\
",stdout) FLUSH;
	ELSE
#endif
#ifdef TERSE
	    fputs(nullart,stdout) FLUSH;
#endif
	return r;
    }
    reply_buf = fetchlines(art,REPLY_LINE);
    from_buf = fetchlines(art,FROM_LINE);
    artid_buf = fetchlines(art,ARTID_LINE);
    ngs_buf = fetchlines(art,NGS_LINE);
    if (!instr(from_buf,sitename) ||
	(!instr(from_buf,logname) &&
	 !instr(reply_buf,logname) &&
#ifdef NEWSADMIN
	 myuid != newsuid &&
#endif
	 myuid != ROOTID ) )
#ifdef VERBOSE
	    IF(verbose)
		fputs("You can't cancel someone else's article\n",stdout)
		  FLUSH;
	    ELSE
#endif
#ifdef TERSE
		fputs("Not your article\n",stdout) FLUSH;
#endif
    else {
	tmpfp = fopen(headname,"w");	/* open header file */
	if (tmpfp == Nullfp) {
	    printf(cantcreate,headname) FLUSH;
	    goto no_cancel;
	}
	interp(buf, (sizeof buf), getval("CANCELHEADER",CANCELHEADER));
	fputs(buf,tmpfp);
	fclose(tmpfp);
	r = doshell(sh,filexp(getval("CANCEL",CANCEL)));
    }
no_cancel:
    free(artid_buf);
    free(ngs_buf);
    free(from_buf);
    free(reply_buf);
    return r;
}

void
reply()
{
    bool incl_body = (*buf == 'R');
    char *maildoer = savestr(filexp(getval("MAILPOSTER",MAILPOSTER)));

    if (artopen(art) == Nullfp) {
#ifdef VERBOSE
	IF(verbose)
	    fputs("\nBut null articles are so dull!  :-)\n",stdout) FLUSH;
	ELSE
#endif
#ifdef TERSE
	    fputs(nullart,stdout) FLUSH;
#endif
	goto no_reply;
    }
    tmpfp = fopen(headname,"w");	/* open header file */
    if (tmpfp == Nullfp) {
	printf(cantcreate,headname) FLUSH;
	goto no_reply;
    }
    interp(buf, (sizeof buf), getval("MAILHEADER",MAILHEADER));
    fputs(buf,tmpfp);
    if (!instr(maildoer,"%h"))
#ifdef VERBOSE
	IF(verbose)
	    printf("\n%s\n(Above lines saved in file %s)\n",buf,headname)
	      FLUSH;
	ELSE
#endif
#ifdef TERSE
	    printf("\n%s\n(Header in %s)\n",buf,headname) FLUSH;
#endif
    if (incl_body) {
	interp(buf, (sizeof buf), getval("YOUSAID",YOUSAID));
	fprintf(tmpfp,"%s\n",buf);
#ifdef ASYNC_PARSE
	parse_maybe(art);
#endif
	fseek(artfp,(long)htype[PAST_HEADER].ht_minpos,0);
	while (fgets(buf,LBUFLEN,artfp) != Nullch) {
	    fprintf(tmpfp,"%s%s",indstr,buf);
	}
	fprintf(tmpfp,"\n");
    }
    fclose(tmpfp);
    interp(cmd_buf, (sizeof cmd_buf), maildoer);
    invoke(cmd_buf,origdir);
    UNLINK(headname);		/* kill the header file */
no_reply:
    free(maildoer);
}

void
followup()
{
    bool incl_body = (*buf == 'F');

    if (artopen(art) == Nullfp) {
#ifdef VERBOSE
	IF(verbose)
	    fputs("\nNull articles give me indigestion!  :-)\n",stdout) FLUSH;
	ELSE
#endif
#ifdef TERSE
	    fputs(nullart,stdout) FLUSH;
#endif
	return;
    }
    tmpfp = fopen(headname,"w");
    if (tmpfp == Nullfp) {
	printf(cantcreate,headname) FLUSH;
	return;
    }
    interp(buf, (sizeof buf), getval("NEWSHEADER",NEWSHEADER));
    fprintf(tmpfp,"%s",buf);
    if (incl_body) {
#ifdef VERBOSE
	if (verbose)
	    fputs("\n\
(Be sure to double-check the attribution against the signature, and\n\
trim the quoted article down as much as possible.)\n\
",stdout) FLUSH;
#endif
	interp(buf, (sizeof buf), getval("ATTRIBUTION",ATTRIBUTION));
	fprintf(tmpfp,"%s\n",buf);
#ifdef ASYNC_PARSE
	parse_maybe(art);
#endif
	fseek(artfp,(long)htype[PAST_HEADER].ht_minpos,0);
	while (fgets(buf,LBUFLEN,artfp) != Nullch) {
	    fprintf(tmpfp,"%s%s",indstr,buf);
	}
	fprintf(tmpfp,"\n");
    }
    fclose(tmpfp);
    safecpy(cmd_buf,filexp(getval("NEWSPOSTER",NEWSPOSTER)),sizeof cmd_buf);
    invoke(cmd_buf,origdir);
    UNLINK(headname);
}

void
invoke(cmd,dir)
char *cmd,*dir;
{
    if (chdir(dir)) {
	printf(nocd,dir) FLUSH;
	return;
    }
#ifdef VERBOSE
    IF(verbose)
	printf("\n(leaving cbreak mode; cwd=%s)\nInvoking command: %s\n\n",
	    dir,cmd) FLUSH;
    ELSE
#endif
#ifdef TERSE
	printf("\n(-cbreak; cwd=%s)\nInvoking: %s\n\n",dir,cmd) FLUSH;
#endif
    resetty();			/* make terminal well-behaved */
    doshell(sh,cmd);		/* do the command */
    noecho();			/* set no echo */
    crmode();			/* and cbreak mode */
#ifdef VERBOSE
    IF(verbose)
	fputs("\n(re-entering cbreak mode)\n",stdout) FLUSH;
    ELSE
#endif
#ifdef TERSE
	fputs("\n(+cbreak)\n",stdout) FLUSH;
#endif
    if (chdir(spool) || chdir(ngdir)) {
	printf(nocd,ngdir) FLUSH;
	sig_catcher(0);
    }
}

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

#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;

    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 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 '/':
#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': {
	    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);
	    
	    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);
	    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;
	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 ");
#ifdef VERBOSE
#ifdef TERSE
    printf("%ct ", mp[!verbose]);
#endif
#endif
    printf("%cT ", mp[typeahead]);
#ifdef VERIFY
    printf("%cv ", mp[verify]);
#endif
#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 inews.c.2.pat
cat >inews.c.2.pat <<'!STUFFY!FUNK!'
*** inews.old.c	Tue Apr 30 14:34:19 1985
--- inews.c	Tue Apr 30 14:34:33 1985
***************
*** 416,421
  /*
   *	Link ARTICLE into dir for ngname and update active file.
   */
  localize(ngname)
  char	*ngname;
  {

--- 416,424 -----
  /*
   *	Link ARTICLE into dir for ngname and update active file.
   */
+ #ifdef DOXREFS
+ long
+ #endif
  localize(ngname)
  char	*ngname;
  {
***************
*** 453,458
  			mknewsg(cp, ngname);
  
  		sprintf(bfr, "%s/%ld", cp, ngsize+1);
  #ifdef VMS
  		if ((f2 = creat(bfr, 0666)) >=0 ) {
  			f1 = open(article, 0);

--- 456,466 -----
  			mknewsg(cp, ngname);
  
  		sprintf(bfr, "%s/%ld", cp, ngsize+1);
+ #ifdef LINKART
+ 		if (mylink(ARTICLE, bfr) == 0) break;
+ 				/* on first file inits ARTICLE, on subsequent */
+ 				/* files "links" to first article */
+ #else !LINKART
  #ifdef VMS
  		if ((f2 = creat(bfr, 0666)) >=0 ) {
  			f1 = open(article, 0);
***************
*** 468,473
  		if (link(ARTICLE, bfr) == 0)
  			break;
  #endif !VMS
  		e = errno;	/* keep log from clobbering it */
  		logerr("Cannot install article as %s", bfr);
  		if (e != EEXIST) {

--- 476,482 -----
  		if (link(ARTICLE, bfr) == 0)
  			break;
  #endif !VMS
+ #endif !LINKART
  		e = errno;	/* keep log from clobbering it */
  		logerr("Cannot install article as %s", bfr);
  		if (e != EEXIST) {
***************
*** 494,499
  		strcpy(firstbufname, bfr);
  	sprintf(bfr, "%s/%ld ", ngname, ngsize+1);
  	addhist(bfr);
  	return TRUE;
  }
  

--- 503,509 -----
  		strcpy(firstbufname, bfr);
  	sprintf(bfr, "%s/%ld ", ngname, ngsize+1);
  	addhist(bfr);
+ #ifndef DOXREFS
  	return TRUE;
  #else DOXREFS
  	return ngsize+1;
***************
*** 495,500
  	sprintf(bfr, "%s/%ld ", ngname, ngsize+1);
  	addhist(bfr);
  	return TRUE;
  }
  
  /*

--- 505,513 -----
  	addhist(bfr);
  #ifndef DOXREFS
  	return TRUE;
+ #else DOXREFS
+ 	return ngsize+1;
+ #endif DOXREFS
  }
  
  /*
***************
*** 507,512
  	char c;
  	struct srec srec;	/* struct for sys file lookup	*/
  	int is_invalid = FALSE;
  
  	/* Fill up the rest of header. */
  	if (mode != PROC) {

--- 520,529 -----
  	char c;
  	struct srec srec;	/* struct for sys file lookup	*/
  	int is_invalid = FALSE;
+ #ifdef DOXREFS
+ 	register char *nextxref = header.xref; 
+ 	int numxrefs = 0;
+ #endif DOXREFS
  
  	/* Fill up the rest of header. */
  	if (mode != PROC) {
***************
*** 527,532
  	if (!is_ctl && mode != CREATENG)
  		is_invalid = ngfcheck(mode == PROC);
  
  	/* Write article to temp file. */
  	tfp = xfopen(mktemp(ARTICLE), "w");
  	if ( (c=getc(infp)) == ' ' || c == '\t' ) {

--- 544,556 -----
  	if (!is_ctl && mode != CREATENG)
  		is_invalid = ngfcheck(mode == PROC);
  
+ #ifdef LINKART
+ 	*ARTICLE = '\0';	/* tell mylink() to snarf the name */
+ #else !LINKART
+ #ifdef DOXREFS
+ 	/* Open temp file for article, but link before writing */
+ 	tfp = xfopen(mktemp(ARTICLE), "w");
+ #else DOXREFS
  	/* Write article to temp file. */
  	tfp = xfopen(mktemp(ARTICLE), "w");
  	if ( (c=getc(infp)) == ' ' || c == '\t' ) {
***************
*** 545,550
  		putc('\n',tfp);
  	fclose(tfp);
  	fclose(infp);
  
  	if (is_invalid) {
  		logerr("No valid newsgroups found, moved to junk");

--- 569,576 -----
  		putc('\n',tfp);
  	fclose(tfp);
  	fclose(infp);
+ #endif DOXREFS
+ #endif LINKART
  
  	if (is_invalid) {
  		logerr("No valid newsgroups found, moved to junk");
***************
*** 550,555
  		logerr("No valid newsgroups found, moved to junk");
  		if (localize("junk"))
  			savehist(histline);
  		xxit(1);
  	}
  

--- 576,582 -----
  		logerr("No valid newsgroups found, moved to junk");
  		if (localize("junk"))
  			savehist(histline);
+ #ifndef DOXREFS
  		xxit(1);
  #endif
  	}
***************
*** 551,556
  		if (localize("junk"))
  			savehist(histline);
  		xxit(1);
  	}
  
  	if (time((time_t)0) > (cgtdate(header.subdate) + DFLTEXP) ){

--- 578,584 -----
  			savehist(histline);
  #ifndef DOXREFS
  		xxit(1);
+ #endif
  	}
  #ifdef DOXREFS
  	else
***************
*** 552,558
  			savehist(histline);
  		xxit(1);
  	}
! 
  	if (time((time_t)0) > (cgtdate(header.subdate) + DFLTEXP) ){
  		logerr("Article too old, moved to junk");
  		if (localize("junk"))

--- 580,588 -----
  		xxit(1);
  #endif
  	}
! #ifdef DOXREFS
! 	else
! #endif
  	if (time((time_t)0) > (cgtdate(header.subdate) + DFLTEXP) ){
  		logerr("Article too old, moved to junk");
  		if (localize("junk"))
***************
*** 557,562
  		logerr("Article too old, moved to junk");
  		if (localize("junk"))
  			savehist(histline);
  		xxit(1);
  	}
  

--- 587,593 -----
  		logerr("Article too old, moved to junk");
  		if (localize("junk"))
  			savehist(histline);
+ #ifndef DOXREFS
  		xxit(1);
  #endif
  	}
***************
*** 558,563
  		if (localize("junk"))
  			savehist(histline);
  		xxit(1);
  	}
  
  	if (is_ctl) {

--- 589,595 -----
  			savehist(histline);
  #ifndef DOXREFS
  		xxit(1);
+ #endif
  	}
  #ifdef DOXREFS
  	else
***************
*** 559,565
  			savehist(histline);
  		xxit(1);
  	}
! 
  	if (is_ctl) {
  		control(&header);
  		localize("control");

--- 591,599 -----
  		xxit(1);
  #endif
  	}
! #ifdef DOXREFS
! 	else
! #endif
  	if (is_ctl) {
  #ifndef DOXREFS
  		control(&header);
***************
*** 561,566
  	}
  
  	if (is_ctl) {
  		control(&header);
  		localize("control");
  	} else {

--- 595,601 -----
  	else
  #endif
  	if (is_ctl) {
+ #ifndef DOXREFS
  		control(&header);
  #endif
  		localize("control");
***************
*** 562,567
  
  	if (is_ctl) {
  		control(&header);
  		localize("control");
  	} else {
  		if (s_find(&srec, FULLSYSNAME) == FALSE)

--- 597,603 -----
  	if (is_ctl) {
  #ifndef DOXREFS
  		control(&header);
+ #endif
  		localize("control");
  	} else {
  		if (s_find(&srec, FULLSYSNAME) == FALSE)
***************
*** 566,571
  	} else {
  		if (s_find(&srec, FULLSYSNAME) == FALSE)
  			xerror("Cannot find my name '%s' in %s", FULLSYSNAME, SUBFILE);
  		for (ptr = nbuf; *ptr;) {
  			if (ngmatch(ptr, srec.s_nbuf) || index(ptr,'.') == NULL)
  				localize(ptr);

--- 602,611 -----
  	} else {
  		if (s_find(&srec, FULLSYSNAME) == FALSE)
  			xerror("Cannot find my name '%s' in %s", FULLSYSNAME, SUBFILE);
+ #ifdef DOXREFS
+ 		sprintf(nextxref,"%s ",FULLSYSNAME);
+ 		nextxref += strlen(nextxref);
+ #endif
  		for (ptr = nbuf; *ptr;) {
  #ifndef DOXREFS
  			if (ngmatch(ptr, srec.s_nbuf) || index(ptr,'.') == NULL)
***************
*** 567,572
  		if (s_find(&srec, FULLSYSNAME) == FALSE)
  			xerror("Cannot find my name '%s' in %s", FULLSYSNAME, SUBFILE);
  		for (ptr = nbuf; *ptr;) {
  			if (ngmatch(ptr, srec.s_nbuf) || index(ptr,'.') == NULL)
  				localize(ptr);
  			while (*ptr++)

--- 607,613 -----
  		nextxref += strlen(nextxref);
  #endif
  		for (ptr = nbuf; *ptr;) {
+ #ifndef DOXREFS
  			if (ngmatch(ptr, srec.s_nbuf) || index(ptr,'.') == NULL)
  				localize(ptr);
  #else DOXREFS
***************
*** 569,574
  		for (ptr = nbuf; *ptr;) {
  			if (ngmatch(ptr, srec.s_nbuf) || index(ptr,'.') == NULL)
  				localize(ptr);
  			while (*ptr++)
  				;
  		}

--- 610,624 -----
  #ifndef DOXREFS
  			if (ngmatch(ptr, srec.s_nbuf) || index(ptr,'.') == NULL)
  				localize(ptr);
+ #else DOXREFS
+ 			if (ngmatch(ptr, srec.s_nbuf) ||
+ 			    index(ptr,'.') == NULL) {
+ 				sprintf(nextxref,"%s:%ld ",ptr,localize(ptr));
+ 				numxrefs++;
+ 				while (*nextxref)
+ 				       nextxref++;
+ 			}
+ #endif DOXREFS
  			while (*ptr++)
  				;
  		}
***************
*** 577,582
  			localize("junk");
  		}
  	}
  
  	broadcast();
  	savehist(histline);

--- 627,638 -----
  			localize("junk");
  		}
  	}
+ #ifdef DOXREFS
+ 	if (numxrefs >= 2)
+ 	    *(nextxref-1) = '\0';       /* wipe out the last space */
+ 	else
+ 	    header.xref[0] = '\0';      /* wipe out the whole thing */
+ #endif
  
  #ifdef LINKART
  	tfp = xfopen(ARTICLE,"w");	/* open 1st article localized */
***************
*** 578,583
  		}
  	}
  
  	broadcast();
  	savehist(histline);
  	xxit(0);

--- 634,669 -----
  	    header.xref[0] = '\0';      /* wipe out the whole thing */
  #endif
  
+ #ifdef LINKART
+ 	tfp = xfopen(ARTICLE,"w");	/* open 1st article localized */
+ #endif
+ 
+ #if defined(LINKART) || defined(DOXREFS)
+ 	/* Now that xref is constructed, write article to temp file. */
+ 	/* (We ought to detect no room at this point and clean up.) */ 
+ 	if ( (c=getc(infp)) == ' ' || c == '\t' ) {
+ 		header.intnumlines++;
+ 		sprintf(header.numlines,"%d",header.intnumlines);
+ 	}
+ 	lhwrite(&header, tfp);
+ 	/* Kludge to get around article truncation problem */
+ 	if (c == ' ' || c == '\t' )
+ 		putc('\n', tfp);
+ 	putc(c,tfp);
+ 	while (fgets(bfr, BUFLEN, infp) != NULL)
+ 		fputs(bfr, tfp);
+ 
+ 	if (bfr[strlen(bfr)-1] != '\n')
+ 		putc('\n',tfp);
+ 	fclose(tfp);
+ 	fclose(infp);
+ #endif LINKART || DOXREFS
+ 
+ #ifdef DOXREFS
+ 	if (is_ctl)	/* moved here cuz checkgroups uses ARTICLE! */
+ 		control(&header);
+ #endif
+ 
  	broadcast();
  	savehist(histline);
  	xxit(0);
***************
*** 853,855
  	}
  	return(NULL);
  }

--- 939,963 -----
  	}
  	return(NULL);
  }
+ 
+ #ifdef LINKART
+ mylink(tmpart,linkfrom)
+ char *tmpart, *linkfrom;
+ {
+     struct stat statbuf;
+ 
+     if (stat(linkfrom,&statbuf)==0)
+ 	return -1;
+     if (!*tmpart)                       /* first article? */
+ 	strcpy(tmpart,linkfrom);        /* just remember name */
+     else {
+ 	FILE *linkfp = fopen(linkfrom,"w");
+ 
+ 	if (!linkfp)
+ 	    return -1;
+ 	fprintf(linkfp,"%s\n",tmpart);  /* do "symbolic link" */
+ 	fclose(linkfp);
+     }
+     return 0;
+ }
+ #endif LINKART
!STUFFY!FUNK!
echo Extracting help.c
cat >help.c <<'!STUFFY!FUNK!'
/* $Header: help.c,v 4.3 85/05/01 11:38:59 lwall Exp $
 *
 * $Log:	help.c,v $
 * Revision 4.3  85/05/01  11:38:59  lwall
 * Baseline for release with 4.3bsd.
 * 
 */

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

void
help_init()
{
    ;
}

int
help_page()
{
    int cmd;

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

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

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

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

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

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

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

/* search for an article containing some pattern */

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

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

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

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

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

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

!STUFFY!FUNK!
echo Extracting inews.c.1.pat
cat >inews.c.1.pat <<'!STUFFY!FUNK!'
*** inews.c.1.std	Tue Oct  2 16:09:59 1984
--- inews.c.1	Fri Sep 21 14:50:49 1984
***************
*** 483,488
  /*
   *	Link ARTICLE into dir for ngname and update active file.
   */
  localize(ngname)
  char	*ngname;
  {

--- 483,491 -----
  /*
   *	Link ARTICLE into dir for ngname and update active file.
   */
+ #ifdef DOXREFS
+ long
+ #endif
  localize(ngname)
  char	*ngname;
  {
***************
*** 515,520
  	}
  	for (;;) {
  		sprintf(bfr, "%s/%ld", dirname(ngname), ngsize+1);
  		if (link(ARTICLE, bfr) == 0) break;
  		e = errno;	/* keep log from clobbering it */
  		fprintf(stderr, "Cannot install article as %s\n", bfr);

--- 518,528 -----
  	}
  	for (;;) {
  		sprintf(bfr, "%s/%ld", dirname(ngname), ngsize+1);
+ #ifdef LINKART
+ 		if (mylink(ARTICLE, bfr) == 0) break;
+ 				/* on first file inits ARTICLE, on subsequent */
+ 				/* files "links" to first article */
+ #else
  		if (link(ARTICLE, bfr) == 0) break;
  #endif
  		e = errno;	/* keep log from clobbering it */
***************
*** 516,521
  	for (;;) {
  		sprintf(bfr, "%s/%ld", dirname(ngname), ngsize+1);
  		if (link(ARTICLE, bfr) == 0) break;
  		e = errno;	/* keep log from clobbering it */
  		fprintf(stderr, "Cannot install article as %s\n", bfr);
  		log("Cannot install article as %s", bfr);

--- 524,530 -----
  				/* files "links" to first article */
  #else
  		if (link(ARTICLE, bfr) == 0) break;
+ #endif
  		e = errno;	/* keep log from clobbering it */
  		fprintf(stderr, "Cannot install article as %s\n", bfr);
  		log("Cannot install article as %s", bfr);
***************
*** 542,547
  		strcpy(firstbufname, bfr);
  	sprintf(bfr, "%s/%ld ", ngname, ngsize+1);
  	addhist(bfr);
  	return TRUE;
  }
  

--- 551,557 -----
  		strcpy(firstbufname, bfr);
  	sprintf(bfr, "%s/%ld ", ngname, ngsize+1);
  	addhist(bfr);
+ #ifndef DOXREFS
  	return TRUE;
  #else DOXREFS
  	return ngsize+1;
***************
*** 543,548
  	sprintf(bfr, "%s/%ld ", ngname, ngsize+1);
  	addhist(bfr);
  	return TRUE;
  }
  
  /*

--- 553,561 -----
  	addhist(bfr);
  #ifndef DOXREFS
  	return TRUE;
+ #else DOXREFS
+ 	return ngsize+1;
+ #endif DOXREFS
  }
  
  /*
***************
*** 553,558
  	register char *ptr;
  	register FILE *tfp;
  	int badgroup = 0, goodgroup = 0;
  
  	/* Fill up the rest of header. */
  	if (mode != PROC) {

--- 566,574 -----
  	register char *ptr;
  	register FILE *tfp;
  	int badgroup = 0, goodgroup = 0;
+ #ifdef DOXREFS
+ 	register char *nextxref = header.xref; 
+ #endif DOXREFS
  
  	/* Fill up the rest of header. */
  	if (mode != PROC) {
***************
*** 565,570
  	if (mode==PROC)
  		log("from %s relay %s", header.from, header.relayversion);
  
  	/* Write article to temp file. */
  	tfp = xfopen(mktemp(ARTICLE), "w");
  	lhwrite(&header, tfp);

--- 581,593 -----
  	if (mode==PROC)
  		log("from %s relay %s", header.from, header.relayversion);
  
+ #ifdef LINKART
+ 	*ARTICLE = '\0';	/* tell mylink() to snarf the name */
+ #else !LINKART
+ #ifdef DOXREFS
+ 	/* Open temp file for article, but link before writing */
+ 	tfp = xfopen(mktemp(ARTICLE), "w");
+ #else DOXREFS
  	/* Write article to temp file. */
  	tfp = xfopen(mktemp(ARTICLE), "w");
  	lhwrite(&header, tfp);
***************
*** 577,582
  	}
  	fclose(tfp);
  	fclose(infp);
  
  	if (is_ctl) {
  		control(&header);

--- 600,607 -----
  	}
  	fclose(tfp);
  	fclose(infp);
+ #endif DOXREFS
+ #endif LINKART
  
  	if (is_ctl) {
  		control(&header);
***************
*** 593,598
  			}
  		}
  	} else {
  		for (ptr = nbuf; *ptr;) {
  			if (*ptr == '-') {
  				while (*ptr++)

--- 618,627 -----
  			}
  		}
  	} else {
+ #ifdef DOXREFS
+ 		sprintf(nextxref,"%s ",SYSNAME);
+ 		nextxref += strlen(nextxref);
+ #endif
  		for (ptr = nbuf; *ptr;) {
  			if (*ptr == '-') {
  				while (*ptr++)
***************
*** 610,615
  			}
  			else
  				goodgroup++;
  			if (*nbuf)
  				localize(ptr);
  			while (*ptr++)

--- 639,645 -----
  			}
  			else
  				goodgroup++;
+ #ifndef DOXREFS
  			if (*nbuf)
  				localize(ptr);
  #else DOXREFS
***************
*** 612,617
  				goodgroup++;
  			if (*nbuf)
  				localize(ptr);
  			while (*ptr++)
  				;
  		}

--- 642,653 -----
  #ifndef DOXREFS
  			if (*nbuf)
  				localize(ptr);
+ #else DOXREFS
+ 			if (*nbuf)
+ 				sprintf(nextxref,"%s:%ld ",ptr,localize(ptr));
+ 			while (*nextxref)
+ 				nextxref++;
+ #endif DOXREFS
  			while (*ptr++)
  				;
  		}
***************
*** 616,621
  				;
  		}
  	}
  
  #ifdef NOFORWARD
  	if (*nbuf)

--- 652,663 -----
  				;
  		}
  	}
+ #ifdef DOXREFS
+ 	if (goodgroup < 2)
+ 	    header.xref[0] = '\0';
+ 	else
+ 	    *(nextxref-1) = '\0';
+ #endif
  
  #ifdef LINKART
  	tfp = xfopen(ARTICLE,"w");	/* open 1st article localized */
***************
*** 617,622
  		}
  	}
  
  #ifdef NOFORWARD
  	if (*nbuf)
  #endif

--- 659,683 -----
  	    *(nextxref-1) = '\0';
  #endif
  
+ #ifdef LINKART
+ 	tfp = xfopen(ARTICLE,"w");	/* open 1st article localized */
+ #endif
+ 
+ #if defined(LINKART) || defined(DOXREFS)
+ 	/* Now that xref is constructed, write article to temp file. */
+ 	/* (We ought to detect no room at this point and clean up.) */ 
+ 	lhwrite(&header, tfp);
+ 	while (fgets(bfr, BUFLEN, infp) != NULL) {
+ 		/*
+ 		if (!strncmp(bfr, "From ", 5))
+ 			putc('>', tfp);
+ 		*/
+ 		fputs(bfr, tfp);
+ 	}
+ 	fclose(tfp);
+ 	fclose(infp);
+ #endif LINKART || DOXREFS
+ 
  #ifdef NOFORWARD
  	if (*nbuf)
  #endif
***************
*** 861,863
  		mclose(fd);
  	}
  }

--- 922,946 -----
  		mclose(fd);
  	}
  }
+ 
+ #ifdef LINKART
+ mylink(tmpart,linkfrom)
+ char *tmpart, *linkfrom;
+ {
+     struct stat statbuf;
+ 
+     if (stat(linkfrom,&statbuf)==0)
+ 	return -1;
+     if (!*tmpart)
+ 	strcpy(tmpart,linkfrom);
+     else {
+ 	FILE *linkfp = fopen(linkfrom,"w");
+ 
+ 	if (!linkfp)
+ 	    return -1;
+ 	fprintf(linkfp,"%s\n",tmpart);
+ 	fclose(linkfp);
+     }
+     return 0;
+ }
+ #endif LINKART
!STUFFY!FUNK!
echo ""
echo "End of kit 6 (of 9)"
cat /dev/null >kit6isdone
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