|
|
1.1 root 1: /*
2: * This software is Copyright 1986 by Rick Adams.
3: *
4: * Permission is hereby granted to copy, reproduce, redistribute or
5: * otherwise use this software as long as: there is no monetary
6: * profit gained specifically from the use or reproduction or this
7: * software, it is not sold, rented, traded or otherwise marketed, and
8: * this copyright notice is included prominently in any copy
9: * made.
10: *
11: * The author make no claims as to the fitness or correctness of
12: * this software for any use whatsoever, and it is provided as is.
13: * Any use of this software is at the user's own risk.
14: *
15: * rfuncs2 - more routines needed by readr.
16: */
17:
18: #ifdef SCCSID
19: static char *SccsId = "@(#)rfuncs2.c 1.35 3/21/87";
20: #endif /* SCCSID */
21:
22: /*LINTLIBRARY*/
23:
24: #include "rparams.h"
25:
26: static char lbuf[LBUFLEN];
27: extern char *replyname();
28:
29: FILE *popen();
30:
31: /*
32: * Match title.
33: */
34: titmat(h, titlist)
35: register struct hbuf *h;
36: register char *titlist;
37: {
38: register char *p;
39:
40: while (*titlist != '\0') {
41:
42: if (strcmp(titlist, h->ident) == 0)
43: return TRUE;
44: for (p = h->title; *p != '\0'; p++)
45: if (prefix(p, titlist)) {
46: return TRUE;
47: }
48: while (*titlist++ != '\0')
49: ;
50: }
51: return FALSE;
52: }
53:
54:
55: /*
56: * Save the news item in the user's file.
57: * Allow files with first character as '|' to write article
58: * to program across a pipe.
59: */
60:
61: #define PIPECHAR '|'
62:
63: save(file, to)
64: register char *file, *to;
65: {
66: register FILE *ufp, *hfp;
67: #ifdef u370
68: static struct hbuf hh;
69: #else /* !u370 */
70: struct hbuf hh;
71: #endif /* !u370 */
72: int isprogram = 0;
73: int isnew = 1;
74: register int i;
75:
76: for(i=0;i<NUNREC;i++)
77: hh.unrec[i] = NULL;
78:
79: if ((hfp = art_open(file, "r")) == NULL) {
80: fprintf(stderr, "Can't get article.\n");
81: return;
82: }
83: if (hread(&hh, hfp, TRUE) == NULL) {
84: fprintf(stderr, "Article is garbled.\n");
85: return;
86: }
87: ufp = fopen(to, "r");
88: if (ufp != NULL) {
89: (void) fclose(ufp);
90: isnew = 0;
91: }
92: (void) setgid(gid);
93: (void) setuid(uid);
94: (void) umask(savmask);
95:
96: if (*to == PIPECHAR) {
97: if ((ufp = popen (&to[1], "w")) == NULL) {
98: fprintf(stderr,"Cannot execute %s\n", &to[1]);
99: return;
100: }
101: isprogram++;
102: } else if ((ufp = fopen(to, "a")) == NULL) {
103: fprintf(stderr,"Cannot append to %s.\n", to);
104: return;
105: }
106: /*
107: * V7MAIL code is here to conform to V7 mail format.
108: * If you need a different format to be able to
109: * use your local mail command (such as four ^A's
110: * on the end of articles) substitute it here.
111: */
112: #ifdef MMDF
113: if (!isprogram)
114: fprintf(ufp, "\001\001\001\001\n"); /* MMDF message header */
115: #endif /* MMDF */
116: #ifdef V7MAIL
117: hh.subtime = cgtdate(hh.subdate);
118: fprintf(ufp, "From %s %s", replyname(&hh), ctime(&hh.subtime));
119: #endif
120: hprint(&hh, ufp, 2);
121: #ifdef V7MAIL
122: tprint(hfp, ufp, TRUE);
123: putc('\n', ufp); /* force blank line at end (ugh) */
124: #else
125: tprint(hfp, ufp, FALSE);
126: #endif
127: (void) fclose(hfp);
128: #ifdef MMDF
129: if (!isprogram)
130: fprintf(ufp, "\001\001\001\001\n"); /* MMDF message header */
131: #endif /* MMDF */
132: if (isprogram)
133: (void) pclose (ufp);
134: else
135: (void) fclose(ufp);
136: if (!isprogram)
137: printf("%s: %s\n", to, isnew ? "New file" : "Appended");
138: }
139:
140:
141: /*
142: * Print out the rest of the article.
143: */
144: tprint(ifp, ofp, checkfrom)
145: register FILE *ifp, *ofp;
146: int checkfrom;
147: {
148: while ((fgets(bfr, sizeof bfr, ifp)) != NULL && !SigTrap) {
149: if (checkfrom && strncmp(bfr, "From ", 5) == 0)
150: putc('>', ofp);
151: (void) fputs(bfr, ofp);
152: if (ferror(ofp)) break; /* E.g. disk full */
153: }
154: if (SigTrap)
155: qfflush(ofp);
156: (void) fflush(ofp);
157: fprintf(ofp, (SigTrap ? "\n\n" : "\n"));
158: SigTrap = FALSE;
159: }
160:
161:
162: /*
163: * Print the file header.
164: */
165: hprint(hp, ofp, verbose)
166: register struct hbuf *hp;
167: int verbose;
168: register FILE *ofp;
169: {
170: register char *p1, *p2;
171: char fname[BUFLEN];
172: char *tailpath();
173:
174: fname[0] = '\0'; /* init name holder */
175:
176: if (verbose == 2) {
177: lhwrite(hp, ofp);
178: return;
179: }
180:
181: if (lflag || eflag) {
182: char buf1[80], buf2[200];
183: char *cp;
184:
185: (void) strcpy(bfr, groupdir);
186: for (cp=bfr; *cp; cp++)
187: if (*cp == '/')
188: *cp = '.';
189: (void) sprintf(buf1, "%s/%ld", bfr, bit);
190: (void) sprintf(buf2, "%-20s %s", buf1, hp->title);
191: fprintf(ofp, "%.76s\n", buf2);
192: return;
193: }
194:
195: p1 = index(hp->from, '('); /* Find the sender's full name. */
196: if (p1 == NULL && hp->path[0])
197: p1 = index(hp->path, '(');
198: if (p1 != NULL) {
199: strcpy(fname, p1+1);
200: p2 = index(fname, ')');
201: if (p2 != NULL)
202: *p2 = '\0';
203: }
204:
205: fprintf(ofp, "Subject: %s\n", hp->title);
206: if (!hflag && hp->summary[0])
207: fprintf(ofp, "Summary: %s\n", hp->summary);
208: if (!hflag && hp->keywords[0])
209: fprintf(ofp, "Keywords: %s\n", hp->keywords);
210: if (verbose) {
211: fprintf(ofp, "From: %s\n", hp->from);
212: fprintf(ofp, "Path: %s\n", hp->path);
213: if (hp->organization[0])
214: fprintf(ofp, "Organization: %s\n", hp->organization);
215: }
216: else {
217: if (p1 != NULL)
218: *--p1 = '\0'; /* bump over the '(' */
219: #ifdef INTERNET
220: /*
221: * Prefer Path line if it's in internet format, or if we don't
222: * understand internet format here, or if there is no reply-to.
223: */
224: fprintf(ofp, "From: %s", hp->from);
225: #else
226: fprintf(ofp, "Path: %s", tailpath(hp));
227: #endif
228: if (fname[0] || hp->organization[0]) {
229: if (fname[0] == '\0') {
230: (void) strcpy(fname,hp->from);
231: p2 = index(fname,'@');
232: if (p2)
233: *p2 = '\0';
234: }
235: fprintf(ofp, " (%s", fname);
236: if (hp->organization[0] && !hflag)
237: fprintf(ofp, " @ %s", hp->organization);
238: fprintf(ofp, ")");
239: }
240: fprintf(ofp, "\n");
241: if (p1 != NULL)
242: *p1 = ' ';
243: }
244:
245: if (verbose) {
246: fprintf(ofp, "Newsgroups: %s\n", hp->nbuf);
247: fprintf(ofp, "Date: %s\n", hp->subdate);
248: if (hp->sender[0])
249: fprintf(ofp, "Sender: %s\n", hp->sender);
250: if (hp->replyto[0])
251: fprintf(ofp, "Reply-To: %s\n", hp->replyto);
252: if (hp->followto[0])
253: fprintf(ofp, "Followup-To: %s\n", hp->followto);
254: }
255: else if (index(hp->nbuf, ',') || strcmp(groupdir, "junk") == 0)
256: fprintf(ofp, "Newsgroups: %s\n", hp->nbuf);
257:
258: if (pflag || ofp != stdout)
259: putc('\n', ofp);
260: }
261:
262:
263: /*
264: * If ofp != stdout, close it and run the script in coptbuf.
265: */
266: cout(ofp)
267: FILE *ofp;
268: {
269: register char *p, *q, *r;
270:
271: if (ofp == stdout || ofp == NULL)
272: return;
273: (void) fclose(ofp);
274: p = coptbuf;
275: q = lbuf;
276: while ((*q = *p++) != '\0')
277: if (*q++ == FMETA) {
278: q--;
279: r = outfile;
280: while ((*q++ = *r++) != '\0')
281: ;
282: q--;
283: }
284: fwait(fsubr(ushell, lbuf, (char *)NULL));
285: (void) unlink(outfile);
286: }
287:
288:
289: cdump(ofp)
290: register FILE *ofp;
291: {
292: if (ofp == stdout)
293: return;
294: fclose(ofp);
295: unlink(outfile);
296: }
297:
298:
299: /*
300: * Quiet 'flush'.
301: * Empty (without fflush()) the buffer for stream fp.
302: */
303: /* ARGSUSED */
304: qfflush(fp)
305: FILE *fp;
306: {
307: #ifdef fileno
308: int fno, err;
309:
310: fno = fileno(fp);
311: err = ferror(fp);
312: fileno(fp) = -1;
313: (void) fflush(fp);
314: fileno(fp) = fno;
315: if (!err)
316: (void) clearerr(fp);
317: #endif /* fileno */
318: }
319:
320: /*
321: * Count the number of remaining lines in file fp.
322: * Do not move the file pointer.
323: */
324: linecnt(fp)
325: FILE *fp;
326: {
327: long curpos;
328: register int nlines = 0;
329: register int c;
330:
331: if (fp == NULL)
332: return 0;
333: curpos = ftell(fp);
334: while ((c = getc(fp)) != EOF)
335: if (c == '\n')
336: nlines++;
337: (void) fseek(fp, curpos, 0);
338: return nlines;
339: }
340:
341:
342: /*
343: * Transmit file to system.
344: */
345: transmit(sp, file)
346: register struct srec *sp;
347: char *file;
348: {
349: register FILE *ifp, *ofp;
350: register int c, i;
351: #ifdef u370
352: static struct hbuf hh;
353: #else /* !u370 */
354: struct hbuf hh;
355: #endif /* !u370 */
356: char TRANS[BUFLEN];
357:
358: #ifdef DEBUG
359: fprintf(stderr, "xmit %s to %s using %s\n", file, sp->s_name, sp->s_xmit);
360: #endif
361: bzero((char *)&hh, sizeof hh);
362: ifp = xart_open(file, "r");
363: if (hread(&hh, ifp, TRUE) == NULL)
364: return;
365: strcpy(TRANS, "/tmp/trXXXXXX");
366: ofp = xfopen(mktemp(TRANS), "w");
367: if (index(sp->s_flags, 'A') == NULL)
368: hwrite(&hh, ofp);
369: else {
370: #ifdef OLD
371: fprintf(ofp, "A%s\n%s\n%s!%s\n%s\n%s\n", oident(hh.ident), hh.nbuf, PATHSYSNAME,
372: hh.path, hh.subdate, hh.title);
373: #else /* !OLD */
374: logerr("Must have OLD defined to use A flag for xmit");
375: unlink(TRANS);
376: return;
377: #endif /* !OLD */
378: }
379: while ((c = getc(ifp)) != EOF)
380: putc(c, ofp);
381: (void) fclose(ifp);
382: (void) fclose(ofp);
383: for (i=0;i<NUNREC;i++)
384: if (hh.unrec[i] != NULL)
385: free(hh.unrec[i]);
386: if (*sp->s_xmit == '\0' || strpbrk(sp->s_flags, "FUMH"))
387: (void) sprintf(bfr, DFTXMIT, sp->s_name, TRANS);
388: else
389: (void) sprintf(bfr, "(%s) < %s", sp->s_xmit, TRANS);
390: #ifdef DEBUG
391: fprintf(stderr, "%s\n", bfr);
392: #endif
393: (void) system(bfr);
394: (void) unlink(TRANS);
395: }
396:
397:
398: /*
399: * Cancel the article whose header is in hp, by posting a control message
400: * to cancel it. The scope of the control message depends on who would
401: * really be willing to cancel it. It is sent as far as it will do any good.
402: * notauthor is true iff the person posting this article is not the
403: * real author of the article being cancelled.
404: */
405: cancel(ofp, hp, notauthor)
406: FILE *ofp;
407: struct hbuf *hp;
408: int notauthor;
409: {
410: int pid;
411:
412: fflush(ofp);
413: pid = vfork();
414: if (pid < 0) {
415: perror("readnews: cancel");
416: return 0;
417: }
418: if (pid > 0)
419: return 0;
420: if (notauthor)
421: (void) sprintf(bfr, "%s/%s -c 'cancel %s' -n %s -d %s < /dev/null",
422: LIB, "inews", hp->ident, hp->nbuf,
423: #ifdef ORGDISTRIB
424: ORGDISTRIB);
425: #else /* !ORGDISTRIB */
426: "local");
427: #endif /* !ORGDISTRIB */
428: else {
429: if (hp->distribution[0] == '\0')
430: (void) sprintf(bfr, "%s/%s -c 'cancel %s' -n %s < /dev/null",
431: LIB, "inews", hp->ident, hp->nbuf);
432: else
433: (void) sprintf(bfr, "%s/%s -c 'cancel %s' -n %s -d %s < /dev/null",
434: LIB, "inews", hp->ident, hp->nbuf, hp->distribution);
435: }
436: execl("/bin/sh", "sh", "-c", bfr, (char *) 0);
437: perror(bfr);
438: for ( ; ; )
439: exit(1);
440: }
441:
442:
443: dash(num, ofp)
444: register int num;
445: register FILE *ofp;
446: {
447: register int i;
448:
449: for (i = 0; i < num; i++)
450: putc('-', ofp);
451: putc('\n', ofp);
452: }
453:
454:
455: help(ofp)
456: register FILE *ofp;
457: {
458: register FILE *fp;
459: register int c;
460: char temp[BUFLEN];
461:
462: if (cflag) {
463: oneline:
464: fprintf(ofp, "(n)ext re(p)rint (w)rite (q)uit (r)eply\
465: (c)ancel -[n] +[n] (f)ollowup (N)ext (U)nsubscribe (v)ersion\n");
466: return;
467: }
468: (void) sprintf(temp, "%s/%s", LIB, "help");
469: if ((fp = fopen(temp, "r")) == NULL) {
470: fprintf(ofp, "No help file.\n");
471: goto oneline;
472: }
473: while ((c = getc(fp)) != EOF && !SigTrap)
474: putc(c, ofp);
475: (void) fclose(fp);
476: }
477:
478:
479: pout(ofp)
480: FILE *ofp;
481: {
482: register char *p, *q, *r;
483:
484: p = PAGER;
485: q = lbuf;
486: while ((*q = *p++) != '\0')
487: if (*q++ == FMETA) {
488: q--;
489: r = filename;
490: while ((*q++ = *r++) != '\0')
491: ;
492: q--;
493: }
494: fwait(fsubr(ushell, lbuf, (char *)NULL));
495: fprintf(ofp, "\n");
496: }
497:
498: /*
499: * Print a very brief version of the date in question.
500: */
501: char *
502: briefdate(datestr)
503: char *datestr;
504: {
505: time_t dt, now;
506: char *tmstr;
507: char *wkday, *monthdate, *timeofday;
508: static char rbuf[20];
509:
510: dt = cgtdate(datestr);
511: tmstr = ctime(&dt);
512:
513: wkday = tmstr; tmstr[3] = '\0';
514: monthdate = tmstr+4; tmstr[10] = '\0';
515: timeofday = tmstr+11; tmstr[16] = '\0';
516:
517: (void) time(&now);
518: if (now - dt < WEEKS)
519: (void) strcpy(rbuf, wkday);
520: else
521: (void) strcpy(rbuf, monthdate);
522: (void) strcat(rbuf, " ");
523: (void) strcat(rbuf, timeofday);
524: return rbuf;
525: }
526:
527: /*
528: * Return TRUE iff stdout is /dev/null.
529: */
530: ignoring()
531: {
532: struct stat ss, ns;
533:
534: if (fstat(1, &ss) < 0)
535: return FALSE;
536: if (stat("/dev/null", &ns) < 0)
537: return FALSE;
538: if (ss.st_dev == ns.st_dev && ss.st_rdev == ns.st_rdev)
539: return TRUE;
540: return FALSE;
541: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.