1: /*
2: * digest - process ARPANET digests
3: *
4: * digest(ifile, ofile, header)
5: * FILE *ifile, *ofile;
6: * struct header *header;
7: *
8: * returns: TRUE EOF reached, exit from readnews.
9: * FALSE normal exit, continue reading news.
10: */
11:
12: #ifdef SCCSID
13: static char *SccsId = "@(#)digest.c 1.6 4/16/85";
14: #endif /* SCCSID */
15:
16: #include "rparams.h"
17:
18: struct art {
19: long a_hdr;
20: long a_bod;
21: int a_blen;
22: int a_hlen;
23: };
24:
25: #define loop for(;;)
26: #define getnum(p, n) for (n=0; *p>='0' && *p<='9'; p++) n = n*10 + *p-'0'
27: #define errchk(p) if (*p) goto badopt
28:
29: #define MAXART 128
30:
31: struct art *arts;
32: int lastart;
33:
34: digest(ifp, ofp, h)
35: FILE *ifp, *ofp;
36: struct hbuf *h;
37: {
38: register int n, curart;
39: struct art artbuf[MAXART];
40: int printh, eod, nomore;
41: char cbuf[BUFLEN], *cmd;
42:
43: arts = artbuf;
44: printh = TRUE;
45: nomore = eod = FALSE;
46: curart = 1;
47:
48: if (dscan(ifp))
49: return FALSE;
50:
51: dprint(0, ifp, ofp);
52:
53: loop {
54: if (nomore) break;
55: if (curart < 1) {
56: curart = 1;
57: eod = nomore = FALSE;
58: }
59: if (curart > lastart) curart = lastart;
60: if (eod) nomore = TRUE;
61: if (printh && !nomore)
62: (void) dhprint(curart, ifp, ofp);
63: getcmd:
64: loop {
65: SigTrap = FALSE;
66: fprintf(ofp, "Digest article %d of %d ", curart, lastart);
67: if (curart==lastart && nomore)
68: fprintf(ofp, "Last digest article ");
69: fprintf(ofp, "(%d lines) More? [%s] ",
70: arts[curart].a_blen, nomore?"snq":"ynq");
71: (void) fflush(ofp);
72: cmd = cbuf;
73: if (fgets(cmd, BUFLEN, stdin))
74: break;
75: if (!SigTrap)
76: return(TRUE);
77: putc('\n', ofp);
78: }
79: (void) nstrip(cmd);
80: while (*cmd==' ' || *cmd=='\t')
81: cmd++;
82: printh = TRUE;
83:
84: switch (*cmd++) {
85: case '#':
86: fprintf(ofp, "%d articles in digest\n", lastart);
87: (void) fflush(ofp);
88: printh = FALSE;
89: break;
90:
91: case '$':
92: curart = lastart;
93: break;
94:
95: case '!':
96: fwait(fsubr(ushell, cmd, (char *)NULL));
97: fprintf(ofp, "!\n");
98: printh = FALSE;
99: break;
100:
101: case '\0':
102: if (nomore) {
103: putc('\n', ofp);
104: return(FALSE);
105: }
106: cmd--;
107: case 'y':
108: case 'p':
109: errchk(cmd);
110: dprint(curart++, ifp, ofp);
111: if (curart > lastart)
112: eod = TRUE;
113: break;
114:
115: case 'n':
116: errchk(cmd);
117: if (++curart > lastart) {
118: putc('\n', ofp);
119: return(FALSE);
120: }
121: break;
122:
123: case '+':
124: getnum(cmd, n);
125: errchk(cmd);
126: if (nomore) {
127: putc('\n', ofp);
128: return(FALSE);
129: }
130: if (n) curart += n;
131: else {
132: curart += 1;
133: if (curart > lastart)
134: eod = TRUE;
135: }
136: break;
137:
138: case '-':
139: getnum(cmd, n);
140: errchk(cmd);
141: eod = nomore = FALSE;
142: curart -= (n) ? n : 1;
143: break;
144:
145: case '0': case '1': case '2': case '3': case '4':
146: case '5': case '6': case '7': case '8': case '9':
147: cmd--;
148: getnum(cmd, n);
149: errchk(cmd);
150: curart = n;
151: eod = nomore = FALSE;
152: break;
153:
154: case 'q':
155: case 'x':
156: putc('\n', ofp);
157: return(FALSE);
158:
159: case '?':
160: fprintf(ofp, "\nDigester options:\n\n");
161: fprintf(ofp, "y\tyes, print article.\n");
162: fprintf(ofp, "n\tno, go to next article.\n");
163: fprintf(ofp, "q\texit from digester.\n");
164: fprintf(ofp, "h\tprint article header.\n");
165: fprintf(ofp, "s file\tsave article in file.\n");
166: fprintf(ofp, "t\ttable of contents.\n");
167: fprintf(ofp, "+[n]\tforward n articles (1).\n");
168: fprintf(ofp, "-[n]\tback n articles (1).\n");
169: fprintf(ofp, "\nh and s may be followed by '-'\n");
170: (void) fflush(ofp);
171: break;
172:
173: case 'h':
174: n = curart;
175: if (*cmd=='-') {
176: cmd++;
177: if (n > 1) n--;
178: }
179: errchk(cmd);
180: (void) dhprint(n, ifp, ofp);
181: nomore = printh = FALSE;
182: if (n!=curart)
183: putc('\n', ofp);
184: break;
185:
186: case 's':
187: case 'w':
188: n = curart;
189: if (*cmd=='-') {
190: cmd++;
191: if (n > 1) n--;
192: }
193: while (*cmd==' ' || *cmd=='\t')
194: cmd++;
195: dsaveart(n, ifp, ofp, cmd);
196: nomore = printh = FALSE;
197: if (n!=curart)
198: putc('\n', ofp);
199: break;
200:
201: case 'H':
202: errchk(cmd);
203: hprint(h, ofp, 1);
204: eod = nomore = FALSE;
205: break;
206:
207: case 'T':
208: case 't':
209: errchk(cmd);
210: if (cmd[-1]=='T')
211: hprint(h, ofp, 0);
212: dprint(0, ifp, ofp);
213: eod = nomore = FALSE;
214: break;
215:
216: default:
217: badopt:
218: if (!nomore)
219: fprintf(ofp, "y (yes), n (no), ");
220: fprintf(ofp, "q (quit), s file (save), h (header), t (table of contents)\n");
221: fprintf(ofp, "? for help\n");
222: goto getcmd;
223: }
224: }
225: putc('\n', ofp);
226: return(FALSE);
227: }
228:
229: dscan(ifp)
230: register FILE *ifp;
231: {
232: char scanbuf[BUFLEN];
233: register int n, len;
234: register char *s;
235: register long pos;
236: short wasblank, ishead;
237:
238: n = len = 0;
239: wasblank = FALSE;
240: s = scanbuf;
241: arts[0].a_bod = arts[1].a_hdr = ftell(ifp);
242: arts[0].a_hdr = 0L;
243: arts[1].a_bod = -1L;
244:
245: loop {
246: if (SigTrap)
247: return(TRUE);
248: pos = ftell(ifp);
249: if (fgets(s, BUFLEN, ifp)==NULL)
250: *s = '\0';
251: if (wasblank && isheader(s)) {
252: long lastpos;
253: short isblank;
254: short nhlines;
255: arts[n++].a_blen = len;
256: len = 0;
257: nhlines = 0;
258: arts[n].a_hdr = pos;
259: isblank = FALSE;
260: ishead = TRUE;
261: do {
262: lastpos = pos;
263: wasblank = isblank;
264: nhlines++;
265: pos = ftell(ifp);
266: if (fgets(s, BUFLEN, ifp)==NULL)
267: *s = '\0';
268: else
269: len++;
270: isblank = (*s=='\n') ? TRUE : FALSE;
271: if (isblank && nhlines==1)
272: /* one liner--not a header */
273: break;
274: if (!ishead || (s[0] != ' ' && s[0] != '\t'))
275: ishead = isheader(s);
276: } while ((isblank && !wasblank) || ishead);
277: if ((!isblank && !wasblank) || nhlines < 2) {
278: /* oops! not a header... back off */
279: arts[n].a_hdr = arts[n-1].a_bod;
280: len += arts[--n].a_blen;
281: } else {
282: if (wasblank)
283: pos = lastpos;
284: arts[n].a_hlen = len;
285: arts[n].a_bod = arts[n+1].a_hdr = pos;
286: arts[n+1].a_bod = -1L;
287: arts[n+1].a_hlen = 3; /* average header len */
288: len = 0;
289: }
290: }
291: if (*s=='\0')
292: break;
293: wasblank = (*s=='\n') ? TRUE : FALSE;
294: len++;
295: }
296: arts[n].a_blen = len;
297: arts[n+1].a_hdr = pos;
298: lastart = n;
299: return FALSE;
300: }
301:
302: dhprint(art, ifp, ofp)
303: register int art;
304: register FILE *ifp, *ofp;
305: {
306: register char c;
307: register long pos = arts[art].a_hdr;
308: register long epos = arts[art].a_bod;
309: register int nlines = 1;
310:
311: putc('\n', ofp);
312: fseek(ifp, pos, 0);
313: while (pos++ < epos && !SigTrap) {
314: if ((c = getc(ifp))=='\n')
315: nlines++;
316: putc(c, ofp);
317: }
318: (void) fflush(ofp);
319: SigTrap = FALSE;
320: return nlines;
321: }
322:
323: dprint(art, ifp, ofp)
324: int art;
325: FILE *ifp, *ofp;
326: {
327: #ifdef PAGE
328: register int cnt;
329: FILE *pfp, *popen();
330:
331: if (art && arts[art].a_blen > 23-arts[art+1].a_hlen && *PAGER) {
332: if (!index(PAGER, FMETA)) {
333: if ((pfp = popen(PAGER, "w"))==NULL)
334: (void) dprinta(art, ifp, ofp);
335: else {
336: cnt = dprinta(art, ifp, pfp) % 23;
337: if (cnt > 23-arts[art+1].a_hlen)
338: while (cnt++ < 24)
339: putc('\n', pfp);
340: (void) pclose(pfp);
341: }
342: } else
343: pout(ofp);
344: } else
345: #endif /* PAGE */
346: (void) dprinta(art, ifp, ofp);
347: }
348:
349: dprinta(art, ifp, ofp)
350: int art;
351: register FILE *ifp, *ofp;
352: {
353: register char c;
354: register long pos = arts[art].a_bod;
355: register long epos = arts[art+1].a_hdr;
356: register int nlines = 0;
357:
358: (void) fseek(ifp, pos, 0);
359: while (pos++ < epos && !SigTrap) {
360: if ((c = getc(ifp))=='\n')
361: nlines++;
362: putc(c, ofp);
363: }
364: (void) fflush(ofp);
365: SigTrap = FALSE;
366: return nlines;
367: }
368:
369: dsaveart(art, ifp, ofp, name)
370: int art;
371: register FILE *ifp, *ofp;
372: register char *name;
373: {
374: register FILE *nfp;
375: char fname[BUFLEN];
376: char *strcat(), *strcpy(), *getenv();
377: register char *nb;
378:
379: while (*name==' ' || *name=='\t')
380: name++;
381:
382: if (*name=='|') {
383: fprintf(ofp, "don't know how to pipe yet.\n");
384: (void) fflush(ofp);
385: return;
386: } else if (*name=='/')
387: (void) strcpy(fname, name);
388: else {
389: if (nb = getenv("NEWSBOX"))
390: (void) strcpy(fname, nb);
391: else
392: (void) strcpy(fname, userhome);
393: (void) strcat(fname, "/");
394: (void) strcat(fname, name);
395: }
396:
397: fprintf(ofp, "Save digest article %d in \"%s\"", art, fname);
398: (void) fflush(ofp);
399: if ((nfp = fopen(fname, "a"))!=NULL) {
400: int ln;
401: ln = dhprint(art, ifp, nfp);
402: ln += dprinta(art, ifp, nfp);
403: fprintf(ofp, " [Appended] %d lines\n", ln);
404: (void) fclose(nfp);
405: } else
406: fprintf(ofp, " cannot append to.\n");
407: }
408:
409: (s)
410: register char *s;
411: {
412: if (isupper(*s) || islower(*s)) {
413: while (*s && *s!=':' && !isspace(*s))
414: s++;
415: if (*s==':' && *++s==' ')
416: return TRUE;
417: }
418: return FALSE;
419: }