1: /* rmail.c - replacement for /bin/rmail */ 2: 3: /* This program has a long, long history. It started as UCB's rmail, and 4: was then modified by OBrien@Rand-Unix to run with MMDF. Then DpK@Brl 5: re-wrote it, and SmB@Unc hacked it up a bit. After that 6: MRose.UCI@Rand-Relay upgraded it to use the nifty MF (mail filtering) 7: system. Finally, the latter stripped it down to work with MH. 8: 9: This program should be used ONLY if you have both "mts mh" and "uucp on" 10: set in your MH configuration. 11: */ 12: 13: 14: #include "../h/mh.h" 15: #include "../h/addrsbr.h" 16: #include "../zotnet/mf.h" 17: #include "../zotnet/tws.h" 18: #include <stdio.h> 19: #include "../zotnet/mts.h" 20: #include <signal.h> 21: 22: 23: #define ADDROK 0 /* okay to use post to deliver message */ 24: #define UUCP 1 /* okay to use uux to deliver message */ 25: #define RETURN 2 /* message loses */ 26: 27: /* */ 28: int pbroke; /* broken-pipe flag */ 29: int rtnflag; /* note was sent back */ 30: 31: char date[BUFSIZ]; /* date of origination from uucp header */ 32: char from[BUFSIZ]; /* accumulated path of sender */ 33: char origsys[BUFSIZ]; /* originating system */ 34: char origpath[BUFSIZ]; /* path from us to originating system */ 35: char usrfrm[BUFSIZ]; /* the 822 version of from[] */ 36: char Mailsys[BUFSIZ]; /* address of the mail agent */ 37: char overseer[BUFSIZ]; /* address of the watchdog */ 38: 39: char mmdf[BUFSIZ]; /* filtered mail file */ 40: 41: char *rtnmessage[] = { 42: " Your message has been intercepted trying to access\n", 43: "a restricted access host (e.g. an ARPANET host). A copy\n", 44: "of your message has been sent to the system administrators.\n", 45: "The text of your message follows.\n\n", 46: NULL 47: }; 48: 49: char rtnbegin[] = 50: " ---------------- Returned Mail Follows --------------\n"; 51: char rtnend[] = 52: " --------------- End of Returned Mail ---------------\n"; 53: 54: char *oopsmessage[] = { 55: "\n\n\tThe system administrators (%s) have been informed of\n", 56: "the problem, but have not been given a copy of your message.\n\n", 57: NULL 58: }; 59: 60: FILE * fromf; /* UUCP "From lines */ 61: FILE * msgf; /* message text */ 62: FILE * pipef; /* output for "post" or "uux" */ 63: 64: 65: int pipeser (); 66: 67: 68: long lseek (); 69: 70: /* */ 71: 72: main (argc, argv) 73: int argc; 74: char **argv; 75: { 76: int cpyback; 77: char *cp, 78: *fromptr, 79: fromwhom[BUFSIZ], 80: linebuf[BUFSIZ], 81: sys[BUFSIZ]; 82: 83: invo_name = r1bindex (*argv, '/'); 84: m_foil (NULLCP); 85: mts_init (invo_name); 86: 87: if (argc < 2) 88: adios (NULLCP, "usage: %s user [user ...]", invo_name); 89: (void) umask (0); 90: (void) setgid (1); 91: (void) setuid (1); 92: 93: (void) sprintf (Mailsys, "%s@%s", Mailer, LocalName ()); 94: if (Overseer == NULL) 95: Overseer = Mailsys; 96: if (index (Overseer, '@') == NULL) { 97: (void) sprintf (overseer, "%s@%s", Overseer, LocalName ()); 98: Overseer = overseer; 99: } 100: 101: (void) mktemp (Errtmp); 102: if (freopen (Errtmp, "w", stderr) == NULL) 103: adios (Errtmp, "unable to create"); 104: (void) dup2 (fileno (stderr), fileno (stdout)); 105: 106: (void) mktemp (Msgtmp); 107: if ((msgf = fdopen (creat (Msgtmp, Tmpmode), "w")) == NULL) 108: adios (Msgtmp, "unable to create"); 109: 110: (void) mktemp (Fromtmp); 111: if ((fromf = fdopen (creat (Fromtmp, Tmpmode), "w")) == NULL) 112: adios (Fromtmp, "unable to create"); 113: 114: /* */ 115: 116: for (;;) { 117: if (fgets (linebuf, sizeof linebuf, stdin) == NULL) 118: break; 119: if (strncmp (linebuf, "From ", 5) 120: && strncmp (linebuf, ">From ", 6)) 121: break; 122: 123: if (linebuf[0] != '>') 124: fputs (">", fromf); 125: fputs (linebuf, fromf); 126: cp = index (linebuf, ' '); 127: fromptr = ++cp; 128: cp = index (cp, ' '); 129: *cp++ = NULL; 130: (void) strcpy (fromwhom, fromptr); 131: (void) strncpy (date, cp, 24); 132: 133: for (;;) { 134: if ((cp = index (cp + 1, 'r')) == NULL) { 135: if ((cp = rindex (fromwhom, '!')) != NULL) { 136: char *p; 137: *cp = NULL; 138: if ((p = rindex (fromwhom, '!')) != NULL) 139: (void) strcpy (origsys, p + 1); 140: else 141: (void) strcpy (origsys, fromwhom); 142: (void) strcat (from, fromwhom); 143: (void) strcat (from, "!"); 144: (void) strcpy (fromwhom, cp + 1); 145: goto out; 146: } 147: (void) strcpy (sys, SystemName ()); 148: (void) strcat (from, sys); 149: (void) strcpy (origsys, sys); 150: (void) strcat (from, "!"); 151: goto out; 152: } 153: if (strncmp (cp, "remote from ", 12) == 0) 154: break; 155: } 156: 157: (void) sscanf (cp, "remote from %s", sys); 158: (void) strcat (from, sys); 159: (void) strcpy (origsys, sys); 160: (void) strcat (from, "!"); 161: out: ; 162: } 163: if (fromwhom[0] == NULL) 164: adios (NULLCP, "no from line"); 165: 166: /* */ 167: 168: (void) strcpy (origpath, from); 169: (void) strcat (from, fromwhom); 170: get_mmdf_addr (from, usrfrm); 171: if ((cp = rindex (usrfrm, '<')) != NULL) { 172: (void) strcpy (usrfrm, ++cp); /* sigh */ 173: if ((cp = rindex (usrfrm, '>')) != NULL) 174: *cp = NULL; 175: } 176: if (usrfrm[0] == NULL) 177: (void) sprintf (usrfrm, "%s!%s%%%s@%s%c", 178: SystemName (), from, UucpChan (), LocalName (), NULL); 179: 180: fputs (linebuf, msgf); 181: if (txtcpy (stdin, msgf) == NOTOK) 182: fputs ("\n *** Problem during receipt from UUCP ***\n", msgf); 183: 184: (void) freopen (Msgtmp, "r", msgf); 185: (void) freopen (Fromtmp, "r", fromf); 186: (void) unlink (Fromtmp); 187: mmdf[0] = NULL; 188: 189: cpyback = 0; 190: for (argv++; --argc > 0;) { 191: rewind (fromf); 192: rewind (msgf); 193: rtnflag = 0; 194: if (deliver (*argv++) == NOTOK && !rtnflag) 195: cpyback++; 196: } 197: 198: (void) fflush (stderr); 199: (void) fflush (stdout); 200: 201: if (cpyback) { 202: rcpy (); 203: zcpy (); 204: } 205: 206: (void) unlink (Msgtmp); 207: if (mmdf[0]) 208: (void) unlink (mmdf); 209: (void) unlink (Errtmp); 210: 211: exit (0); 212: } 213: 214: /* */ 215: 216: deliver (to) 217: char *to; 218: { 219: int i, 220: replyval; 221: char tmpfil[BUFSIZ]; 222: 223: switch (adrcheck (to)) { 224: case ADDROK: 225: if (mmdf[0] == NULL && filter () == NOTOK) 226: (void) strcpy (mmdf, Msgtmp); 227: replyval = xpost (to, mmdf); 228: break; 229: 230: case UUCP: 231: if ((replyval = xuucp (to)) == NOTOK) 232: break; 233: 234: if ((replyval = txtcpy (fromf, pipef)) != NOTOK) 235: replyval = txtcpy (msgf, pipef); 236: i = (pclose (pipef) >> 8) & 0xff; 237: if (replyval != NOTOK) 238: replyval = (i != 0 ? NOTOK : OK); 239: break; 240: 241: /* */ 242: 243: case RETURN: 244: rtnflag++; 245: switch (adrcheck (from)) { 246: case ADDROK: 247: case RETURN: 248: (void) strcpy (tmpfil, "/tmp/rmailXXXXXX"); 249: (void) unlink (mktemp (tmpfil)); 250: if ((pipef = fdopen (creat (tmpfil, Tmpmode), "w")) == NULL) 251: return NOTOK; 252: 253: fprintf (pipef, "Date: %s\nFrom: %s\n", 254: dtimenow (), Mailsys); 255: fprintf (pipef, "To: %s\ncc: %s\n", from, Overseer); 256: rtnmesg (to); 257: (void) fclose (pipef); 258: 259: replyval = xpost (from, tmpfil); 260: (void) unlink (tmpfil); 261: break; 262: 263: case UUCP: 264: if ((replyval = xuucp (from)) == NOTOK) 265: break; 266: 267: fprintf (pipef, "To: %s\ncc: %s\n", from, Overseer); 268: rtnmesg (to); 269: i = (pclose (pipef) >> 8) & 0xff; 270: if (replyval != NOTOK) 271: replyval = (i != 0 ? NOTOK : OK); 272: break; 273: } 274: if (Syscpy) { 275: (void) strcpy (tmpfil, "/tmp/rmailXXXXXX"); 276: (void) unlink (mktemp (tmpfil)); 277: if ((pipef = fdopen (creat (tmpfil, Tmpmode), "w")) == NULL) 278: return NOTOK; 279: 280: fprintf (pipef, "Date: %s\nFrom: %s\n", 281: dtimenow (), Mailsys); 282: fprintf (pipef, "To: %s\ncc: %s\n", usrfrm, Overseer); 283: rtnmesg (to); 284: (void) fclose (pipef); 285: 286: replyval = xpost (Overseer, tmpfil); 287: (void) unlink (tmpfil); 288: } 289: break; 290: } 291: 292: return replyval; 293: } 294: 295: /* */ 296: 297: adrcheck (adr) 298: char *adr; 299: { 300: int type; 301: char *cp, 302: host[BUFSIZ]; 303: struct mailname *mp; 304: 305: if ((cp = getname (adr)) == NULL) 306: return RETURN; 307: mp = getm (cp, NULLCP, 0, AD_HOST, NULLCP); 308: while (getname ("")) 309: continue; 310: if (mp == NULL) 311: return RETURN; 312: 313: type = mp -> m_type; 314: (void) strcpy (host, mp -> m_host); 315: mnfree (mp); 316: if (mp -> m_mbox == NULL) 317: return RETURN; 318: 319: switch (type) { 320: case LOCALHOST: 321: return ADDROK; 322: 323: case UUCPHOST: 324: return (strcmp (host, SystemName ()) ? UUCP : ADDROK); 325: 326: default: 327: if (lookup (origsys, Okhosts) == OK) 328: return ADDROK; 329: return (okhost (host) == NOTOK ? RETURN : ADDROK); 330: } 331: } 332: 333: /* */ 334: 335: okhost (host) 336: char *host; 337: { 338: return (lookup (origsys, Okhosts) == OK 339: || lookup (host, Okhosts) == OK 340: || lookup (host, Okdests) == OK ? OK : NOTOK); 341: } 342: 343: 344: lookup (what, where) 345: char *what, 346: *where; 347: { 348: char *cp, 349: entry[BUFSIZ]; 350: FILE * lookf; 351: 352: if ((lookf = fopen (where, "r")) == NULL) 353: return NOTOK; 354: while (fgets (entry, sizeof entry, lookf) != NULL) { 355: cp = entry; 356: while (*cp != '\n' && *cp != ' ' && *cp != '\t') 357: cp++; 358: *cp = NULL; 359: if (uleq (what, entry)) { 360: (void) fclose (lookf); 361: return OK; 362: } 363: } 364: (void) fclose (lookf); 365: 366: return NOTOK; 367: } 368: 369: 370: /* */ 371: 372: rtnmesg (badadr) 373: char *badadr; 374: { 375: int i; 376: 377: fprintf (pipef, "Subject: Illegal Address (%s)\n\n", badadr); 378: for (i = 0; rtnmessage[i]; i++) 379: fputs (rtnmessage[i], pipef); 380: fputs (rtnbegin, pipef); 381: 382: rewind (fromf); 383: (void) txtcpy (fromf, pipef); 384: rewind (msgf); 385: (void) txtcpy (msgf, pipef); 386: 387: fputs (rtnend, pipef); 388: } 389: 390: 391: txtcpy (frm, to) 392: FILE * frm, *to; 393: { 394: int nread; 395: char buffer[BUFSIZ]; 396: 397: while (!pbroke 398: && (nread = fread (buffer, sizeof (*buffer), BUFSIZ, frm)) > 0) 399: (void) fwrite (buffer, sizeof (*buffer), nread, to); 400: 401: return (ferror (frm) ? NOTOK : OK); 402: } 403: 404: /* */ 405: 406: xpost (addr, file) 407: char *addr, 408: *file; 409: { 410: int i, 411: child_id; 412: 413: for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++) 414: sleep (5); 415: switch (child_id) { 416: case NOTOK: 417: return NOTOK; 418: 419: case OK: 420: execlp (postproc, r1bindex (postproc, '/'), 421: "-deliver", addr, file, NULLCP); 422: fprintf (stderr, "unable to exec "); 423: perror (postproc); 424: _exit (1); 425: 426: default: 427: return (pidwait (child_id, OK) ? NOTOK : OK); 428: } 429: } 430: 431: /* */ 432: 433: xuucp (to) 434: char *to; 435: { 436: char *cp, 437: buffer[BUFSIZ], 438: cmdstr[BUFSIZ]; 439: 440: (void) strcpy (buffer, to); 441: if (cp = index (buffer, '!')) 442: *cp++ = NULL; 443: else { 444: fprintf (stderr, "internal error -- %s has no host\n", to); 445: return NOTOK; 446: } 447: (void) sprintf (cmdstr, "uux -p %s!rmail \\(%s\\)", buffer, cp); 448: 449: if ((pipef = popen (cmdstr, "w")) == NULL) 450: return NOTOK; 451: 452: (void) signal (SIGPIPE, pipeser); 453: pbroke = 0; 454: 455: return OK; 456: } 457: 458: /* */ 459: 460: #ifdef BSD42 461: /* ARGSUSED */ 462: #endif BSD42 463: 464: static int pipeser (i) 465: int i; 466: { 467: #ifndef BSD42 468: (void) signal (i, SIG_IGN); 469: #endif BSD42 470: 471: pbroke = 1; 472: } 473: 474: /* */ 475: 476: rcpy () { 477: int i; 478: char buffer[BUFSIZ], 479: tmpfil[BUFSIZ]; 480: FILE * fp; 481: 482: (void) strcpy (tmpfil, "/tmp/rmailXXXXXX"); 483: (void) unlink (mktemp (tmpfil)); 484: if ((pipef = fdopen (creat (tmpfil, Tmpmode), "w")) == NULL) 485: return; 486: 487: fprintf (pipef, "Date: %s\nFrom: %s\n", dtimenow (), Mailsys); 488: fprintf (pipef, "To: %s\n", usrfrm); 489: fprintf (pipef, "\nProblems sending mail:\n\n"); 490: i = 0; 491: if ((fp = fopen (Errtmp, "r")) != NULL) { 492: while (fgets (buffer, sizeof buffer, fp) != NULL) { 493: if (ferror (pipef)) 494: break; 495: fputs (buffer, pipef); 496: i++; 497: } 498: } 499: if (i == 0) 500: fprintf (pipef, "\tunknown problem\n"); 501: for (i = 0; oopsmessage[i]; i++) 502: fprintf (pipef, oopsmessage[i], Overseer); 503: fputs (rtnbegin, pipef); 504: 505: rewind (fromf); 506: (void) txtcpy (fromf, pipef); 507: rewind (msgf); 508: (void) txtcpy (msgf, pipef); 509: 510: fputs (rtnend, pipef); 511: (void) fclose (pipef); 512: 513: (void) xpost (usrfrm, tmpfil); 514: (void) unlink (tmpfil); 515: } 516: 517: /* */ 518: 519: zcpy () { 520: int i; 521: char buffer[BUFSIZ], 522: tmpfil[BUFSIZ]; 523: FILE * fp; 524: 525: (void) strcpy (tmpfil, "/tmp/rmailXXXXXX"); 526: (void) unlink (mktemp (tmpfil)); 527: if ((pipef = fdopen (creat (tmpfil, Tmpmode), "w")) == NULL) 528: return; 529: 530: fprintf (pipef, "Date: %s\nFrom: %s\n", dtimenow (), Mailsys); 531: fprintf (pipef, "To: %s\n", Mailsys); 532: fprintf (pipef, "\nProblems sending mail for %s (aka %s):\n\n", 533: from, usrfrm); 534: 535: i = 0; 536: if ((fp = fopen (Errtmp, "r")) != NULL) { 537: while (fgets (buffer, sizeof buffer, fp) != NULL) { 538: if (ferror (pipef)) 539: break; 540: fputs (buffer, pipef); 541: i = 1; 542: } 543: (void) fclose (fp); 544: if (i == 0) 545: fprintf (pipef, "\tunknown problem\n"); 546: } 547: else 548: fprintf (pipef, "\tunable to open %s\n", Errtmp); 549: (void) fclose (pipef); 550: 551: (void) xpost (Mailsys, tmpfil); 552: (void) unlink (tmpfil); 553: } 554: 555: /* */ 556: 557: filter () { 558: int i, 559: fd, 560: td; 561: char tmpfil[BUFSIZ], 562: mmdfil[BUFSIZ]; 563: FILE * out; 564: 565: (void) strcpy (tmpfil, "/tmp/rmailXXXXXX"); 566: (void) unlink (mktemp (tmpfil)); 567: if ((fd = creat (tmpfil, Tmpmode)) == NOTOK) 568: return NOTOK; 569: (void) close (fd); 570: if ((fd = open (tmpfil, 2)) == NOTOK) 571: return NOTOK; 572: if ((out = fdopen (fd, "w")) == NULL) { 573: (void) close (fd); 574: return NOTOK; 575: } 576: if ((td = dup (fd)) == NOTOK) { 577: (void) close (fd); 578: return NOTOK; 579: } 580: 581: fprintf (out, "From %s %s\n", from, date); 582: if (txtcpy (msgf, out) == NOTOK) { 583: (void) close (fd); 584: (void) close (td); 585: return NOTOK; 586: } 587: (void) fclose (out); 588: (void) lseek (td, 0L, 0); 589: 590: (void) strcpy (mmdfil, "/tmp/mmdfXXXXXX"); 591: (void) unlink (mktemp (mmdfil)); 592: if ((fd = creat (mmdfil, Tmpmode)) == NOTOK) { 593: (void) close (td); 594: (void) unlink (tmpfil); 595: return NOTOK; 596: } 597: if ((fd = open (mmdfil, 2)) == NOTOK) { 598: (void) close (td); 599: (void) unlink (tmpfil); 600: return NOTOK; 601: } 602: 603: /* */ 604: 605: switch (i = uucp2mmdf (td, fd, TRUE)) { 606: case OK: 607: (void) strcpy (mmdf, mmdfil); 608: break; 609: 610: default: 611: mmdf[0] = NULL; 612: break; 613: } 614: (void) close (td); 615: (void) unlink (tmpfil); 616: (void) close (fd); 617: 618: return (i != OK ? NOTOK : OK); 619: } 620: 621: /* */ 622: 623: get_mmdf_addr (addr, to) 624: char *addr, 625: *to; 626: { 627: struct adrx *adrxp; 628: 629: *to = NULL; 630: if ((adrxp = seekadrx (addr)) == NULL) 631: return; 632: 633: addr_convert (adrxp, to, TRUE); 634: while (seekadrx (NULLCP)) 635: continue; 636: }