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