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