|
|
researchv10 Norman
/*
* digest - process ARPANET digests
*
* Alan Hastings 9/5/82
*
* digest(ifile, ofile, header)
* FILE *ifile, *ofile;
* struct header *header;
*
* returns: TRUE EOF reached, exit from readnews.
* FALSE normal exit, continue reading news.
*/
#include "rparams.h"
struct art {
long a_hdr;
long a_bod;
int a_blen;
int a_hlen;
};
#define loop for(;;)
#define getnum(p, n) for (n=0; *p>='0' && *p<='9'; p++) n = n*10 + *p-'0'
#define errchk(p) if (*p) goto badopt
#define MAXART 128
struct art *arts;
int lastart;
digest(ifp, ofp, h)
FILE *ifp, *ofp;
struct hbuf *h;
{
register int n, curart;
struct art artbuf[MAXART];
int printh, eod, nomore;
char cbuf[BUFLEN], *cmd;
arts = artbuf;
printh = TRUE;
nomore = eod = FALSE;
curart = 1;
if (dscan(ifp))
return(FALSE);
dprint(0, ifp, ofp);
loop {
if (nomore) break;
if (curart < 1) {
curart = 1;
eod = nomore = FALSE;
}
if (curart > lastart) curart = lastart;
if (eod) nomore = TRUE;
if (printh && !nomore)
(void) dhprint(curart, ifp, ofp);
getcmd:
loop {
sigtrap = FALSE;
fprintf(ofp, "Digest article %d of %d ", curart, lastart);
if (curart==lastart && nomore)
fprintf(ofp, "Last digest article ");
fprintf(ofp, "(%d lines) More? [%s] ",
arts[curart].a_blen, nomore?"snq":"ynq");
(void) fflush(ofp);
cmd = cbuf;
if (fgets(cmd, BUFLEN, stdin))
break;
if (!sigtrap)
return(TRUE);
putc('\n', ofp);
}
nstrip(cmd);
while (*cmd==' ' || *cmd=='\t')
cmd++;
printh = TRUE;
switch (*cmd++) {
case '#':
fprintf(ofp, "%d articles in digest\n", lastart);
(void) fflush(ofp);
printh = FALSE;
break;
case '$':
curart = lastart;
break;
case '!':
fwait(fsubr(ushell, cmd, (char *)NULL));
fprintf(ofp, "!\n");
printh = FALSE;
break;
case '\0':
if (nomore) {
putc('\n', ofp);
return(FALSE);
}
cmd--;
case 'y':
case 'p':
errchk(cmd);
dprint(curart++, ifp, ofp);
if (curart > lastart)
eod = TRUE;
break;
case 'n':
errchk(cmd);
if (++curart > lastart) {
putc('\n', ofp);
return(FALSE);
}
break;
case '+':
getnum(cmd, n);
errchk(cmd);
if (nomore) {
putc('\n', ofp);
return(FALSE);
}
if (n) curart += n;
else {
curart += 1;
if (curart > lastart)
eod = TRUE;
}
break;
case '-':
getnum(cmd, n);
errchk(cmd);
eod = nomore = FALSE;
curart -= (n) ? n : 1;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
cmd--;
getnum(cmd, n);
errchk(cmd);
curart = n;
eod = nomore = FALSE;
break;
case 'q':
case 'x':
putc('\n', ofp);
return(FALSE);
case '?':
fprintf(ofp, "\nDigester options:\n\n");
fprintf(ofp, "y\tyes, print article.\n");
fprintf(ofp, "n\tno, go to next article.\n");
fprintf(ofp, "q\texit from digester.\n");
fprintf(ofp, "h\tprint article header.\n");
fprintf(ofp, "s file\tsave article in file.\n");
fprintf(ofp, "t\ttable of contents.\n");
fprintf(ofp, "+[n]\tforward n articles (1).\n");
fprintf(ofp, "-[n]\tback n articles (1).\n");
fprintf(ofp, "\nh and s may be followed by '-'\n");
(void) fflush(ofp);
break;
case 'h':
n = curart;
if (*cmd=='-') {
cmd++;
if (n > 1) n--;
}
errchk(cmd);
(void) dhprint(n, ifp, ofp);
nomore = printh = FALSE;
if (n!=curart)
putc('\n', ofp);
break;
case 's':
case 'w':
n = curart;
if (*cmd=='-') {
cmd++;
if (n > 1) n--;
}
while (*cmd==' ' || *cmd=='\t')
cmd++;
dsaveart(n, ifp, ofp, cmd);
nomore = printh = FALSE;
if (n!=curart)
putc('\n', ofp);
break;
case 'H':
errchk(cmd);
hprint(h, !cflag, ofp, 1);
eod = nomore = FALSE;
break;
case 'T':
case 't':
errchk(cmd);
if (cmd[-1]=='T')
hprint(h, !cflag, ofp, 0);
dprint(0, ifp, ofp);
eod = nomore = FALSE;
break;
default:
badopt:
if (!nomore)
fprintf(ofp, "y (yes), n (no), ");
fprintf(ofp, "q (quit), s file (save), h (header), t (table of contents)\n");
fprintf(ofp, "? for help\n");
goto getcmd;
}
}
putc('\n', ofp);
return(FALSE);
}
dscan(ifp)
register FILE *ifp;
{
char scanbuf[BUFLEN];
register int n, len;
register char *s;
register long pos;
short wasblank;
n = len = 0;
wasblank = FALSE;
s = scanbuf;
arts[0].a_bod = arts[1].a_hdr = ftell(ifp);
arts[0].a_hdr = 0L;
arts[1].a_bod = -1L;
loop {
if (sigtrap)
return(TRUE);
pos = ftell(ifp);
if (fgets(s, BUFLEN, ifp)==NULL)
*s = '\0';
if (wasblank && isheader(s)) {
long lastpos;
short isblank;
short nhlines;
arts[n++].a_blen = len;
len = 0;
nhlines = 0;
arts[n].a_hdr = pos;
isblank = FALSE;
do {
lastpos = pos;
wasblank = isblank;
nhlines++;
pos = ftell(ifp);
if (fgets(s, BUFLEN, ifp)==NULL)
*s = '\0';
else
len++;
isblank = (*s=='\n') ? TRUE : FALSE;
if (isblank && nhlines==1)
/* one liner--not a header */
break;
} while ((isblank && !wasblank) || isheader(s));
if ((!isblank && !wasblank) || nhlines < 2) {
/* oops! not a header... back off */
arts[n].a_hdr = arts[n-1].a_bod;
len += arts[--n].a_blen;
} else {
if (wasblank)
pos = lastpos;
arts[n].a_hlen = len;
arts[n].a_bod = arts[n+1].a_hdr = pos;
arts[n+1].a_bod = -1L;
arts[n+1].a_hlen = 3; /* average header len */
len = 0;
}
}
if (*s=='\0')
break;
wasblank = (*s=='\n') ? TRUE : FALSE;
len++;
}
arts[n].a_blen = len;
arts[n+1].a_hdr = pos;
lastart = n;
return(FALSE);
}
dhprint(art, ifp, ofp)
register int art;
register FILE *ifp, *ofp;
{
register char c;
register long pos = arts[art].a_hdr;
register long epos = arts[art].a_bod;
register int nlines = 1;
putc('\n', ofp);
fseek(ifp, pos, 0);
while (pos++ < epos && !sigtrap) {
if ((c = getc(ifp))=='\n')
nlines++;
putc(c, ofp);
}
(void) fflush(ofp);
sigtrap = FALSE;
return(nlines);
}
dprint(art, ifp, ofp)
int art;
FILE *ifp, *ofp;
{
#ifdef PAGE
register int cnt;
FILE *pfp, *popen();
if (art && arts[art].a_blen > 23-arts[art+1].a_hlen && *PAGER) {
if (!index(PAGER, FMETA)) {
if ((pfp = popen(PAGER, "w"))==NULL)
(void) dprinta(art, ifp, ofp);
else {
cnt = dprinta(art, ifp, pfp) % 23;
if (cnt > 23-arts[art+1].a_hlen)
while (cnt++ < 24)
putc('\n', pfp);
(void) pclose(pfp);
}
} else
pout(ofp);
} else
#endif PAGE
(void) dprinta(art, ifp, ofp);
}
dprinta(art, ifp, ofp)
int art;
register FILE *ifp, *ofp;
{
register char c;
register long pos = arts[art].a_bod;
register long epos = arts[art+1].a_hdr;
register int nlines = 0;
fseek(ifp, pos, 0);
while (pos++ < epos && !sigtrap) {
if ((c = getc(ifp))=='\n')
nlines++;
putc(c, ofp);
}
(void) fflush(ofp);
sigtrap = FALSE;
return(nlines);
}
dsaveart(art, ifp, ofp, name)
int art;
register FILE *ifp, *ofp;
register char *name;
{
register FILE *nfp;
char fname[BUFLEN];
char *strcat(), *strcpy(), *getenv();
register char *nb;
while (*name==' ' || *name=='\t')
name++;
if (*name=='|') {
fprintf(ofp, "don't know how to pipe yet.\n");
(void) fflush(ofp);
return;
} else if (*name=='/')
(void) strcpy(fname, name);
else {
if (nb = getenv("NEWSBOX"))
(void) strcpy(fname, nb);
else
(void) strcpy(fname, userhome);
(void) strcat(fname, "/");
(void) strcat(fname, name);
}
fprintf(ofp, "Save digest article %d in \"%s\"", art, fname);
(void) fflush(ofp);
if ((nfp = fopen(fname, "a"))!=NULL) {
int ln;
ln = dhprint(art, ifp, nfp);
ln += dprinta(art, ifp, nfp);
fprintf(ofp, " [Appended] %d lines\n", ln);
(void) fclose(nfp);
} else
fprintf(ofp, " cannot append to.\n");
}
isheader(s)
register char *s;
{
if (isupper(*s) || islower(*s)) {
while (*s && *s!=':' && !isspace(*s))
s++;
if (*s==':' && *++s==' ')
return(TRUE);
}
return(FALSE);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.