1: /* slocal.c - MH style mailer to write to a local user's mailbox */ 2: 3: /* This program implements mail delivery in the MH/MMDF style. 4: 5: Under SendMail, users should add the line 6: 7: "| /usr/local/lib/mh/slocal" 8: 9: to their $HOME/.forward file. 10: 11: Under MMDF-I, users should (symbolically) link /usr/local/lib/mh/slocal 12: to $HOME/bin/rcvmail. 13: 14: Under stand-alone MH, post will automatically run this during local 15: delivery. 16: 17: This program should be used ONLY if you have "mts sendmail" or "mts mh" 18: or "mts mmdf1" set in your MH configuration. 19: */ 20: 21: /* */ 22: 23: #include "../h/mh.h" 24: #include "../h/dropsbr.h" 25: #include "../h/rcvmail.h" 26: #include "../zotnet/tws.h" 27: #include "../zotnet/mts.h" 28: #include <pwd.h> 29: #include <signal.h> 30: #ifndef V7 31: #include <sys/ioctl.h> 32: #endif not V7 33: #include <sys/stat.h> 34: #include <utmp.h> 35: 36: 37: #define NVEC 100 38: 39: /* */ 40: 41: static struct swit switches[] = { 42: #define ADDRSW 0 43: "addr address", 0, 44: #define USERSW 1 45: "user name", 0, 46: #define FILESW 2 47: "file file", 0, 48: #define SENDSW 3 49: "sender address", 0, 50: #define MBOXSW 4 51: "mailbox file", 0, 52: #define HOMESW 5 53: "home directory", 0, 54: 55: #define MAILSW 6 56: "maildelivery file", 0, 57: 58: #define VERBSW 7 59: "verbose", 0, 60: #define NVERBSW 8 61: "noverbose", 0, 62: 63: #define DEBUGSW 9 64: "debug", 0, 65: 66: #define HELPSW 10 67: "help", 4, 68: 69: NULL, NULL 70: }; 71: 72: /* */ 73: 74: static int debug = 0; 75: static int globbed = 0; 76: static int parsed = 0; 77: static int utmped = 0; 78: static int verbose = 0; 79: 80: static char *addr = NULLCP; 81: static char *user = NULLCP; 82: static char *info = NULLCP; 83: static char *file = NULLCP; 84: static char *sender = NULLCP; 85: static char *mbox = NULLCP; 86: static char *home = NULLCP; 87: 88: 89: static struct passwd *pw; 90: 91: 92: static char ddate[BUFSIZ]; 93: 94: struct tws *now; 95: 96: 97: static jmp_buf myctx; 98: 99: /* */ 100: 101: static struct pair { 102: char *p_name; 103: char *p_value; 104: 105: char p_flags; 106: #define P_NIL 0x00 107: #define P_ADR 0x01 108: #define P_HID 0x02 109: #define P_CHK 0x04 110: }; 111: 112: struct pair *lookup (); 113: 114: 115: static struct pair hdrs[NVEC + 1] = { 116: "source", NULL, P_HID, 117: "addr", NULL, P_HID, 118: 119: "Return-Path", NULL, P_ADR, 120: "Reply-To", NULL, P_ADR, 121: "From", NULL, P_ADR, 122: "Sender", NULL, P_ADR, 123: "To", NULL, P_ADR, 124: "cc", NULL, P_ADR, 125: "Resent-Reply-To", NULL, P_ADR, 126: "Resent-From", NULL, P_ADR, 127: "Resent-Sender", NULL, P_ADR, 128: "Resent-To", NULL, P_ADR, 129: "Resent-cc", NULL, P_ADR, 130: 131: NULL 132: }; 133: 134: 135: static struct pair vars[] = { 136: "sender", NULL, P_NIL, 137: "address", NULL, P_NIL, 138: "size", NULL, P_NIL, 139: "reply-to", NULL, P_CHK, 140: "info", NULL, P_NIL, 141: 142: NULL 143: }; 144: 145: /* */ 146: 147: extern char **environ; 148: 149: void adorn (); 150: int alrmser (); 151: 152: 153: long lseek (); 154: #ifdef SYS5 155: struct passwd *getpwnam (); 156: #endif SYS5 157: 158: /* */ 159: 160: /* ARGSUSED */ 161: 162: main (argc, argv, envp) 163: int argc; 164: char **argv, 165: **envp; 166: { 167: int fd; 168: FILE *fp = stdin; 169: char *cp, 170: *mdlvr = NULL, 171: buf[100], 172: from[BUFSIZ], 173: mailbox[BUFSIZ], 174: tmpfil[BUFSIZ], 175: **argp = argv + 1; 176: 177: invo_name = r1bindex (*argv, '/'); 178: m_foil (NULLCP); 179: mts_init (invo_name); 180: 181: /* */ 182: 183: while (cp = *argp++) { 184: if (*cp == '-') 185: switch (smatch (++cp, switches)) { 186: case AMBIGSW: 187: ambigsw (cp, switches); 188: done (1); 189: case UNKWNSW: 190: adios (NULLCP, "-%s unknown", cp); 191: case HELPSW: 192: (void) sprintf (buf, "%s [switches] [address info sender]", 193: invo_name); 194: help (buf, switches); 195: done (1); 196: 197: case ADDRSW: 198: if (!(addr = *argp++))/* allow -xyz arguments */ 199: adios (NULLCP, "missing argument to %s", argp[-2]); 200: continue; 201: case USERSW: 202: if (!(user = *argp++))/* allow -xyz arguments */ 203: adios (NULLCP, "missing argument to %s", argp[-2]); 204: continue; 205: case FILESW: 206: if (!(file = *argp++) || *file == '-') 207: adios (NULLCP, "missing argument to %s", argp[-2]); 208: continue; 209: case SENDSW: 210: if (!(sender = *argp++))/* allow -xyz arguments */ 211: adios (NULLCP, "missing argument to %s", argp[-2]); 212: continue; 213: case MBOXSW: 214: if (!(mbox = *argp++) || *mbox == '-') 215: adios (NULLCP, "missing argument to %s", argp[-2]); 216: continue; 217: case HOMESW: 218: if (!(home = *argp++) || *home == '-') 219: adios (NULLCP, "missing argument to %s", argp[-2]); 220: continue; 221: 222: case MAILSW: 223: if (!(cp = *argp++) || *cp == '-') 224: adios (NULLCP, "missing argument to %s", argp[-2]); 225: if (mdlvr) 226: adios (NULLCP, "only one maildelivery file at a time!"); 227: mdlvr = cp; 228: continue; 229: 230: case VERBSW: 231: verbose++; 232: continue; 233: case NVERBSW: 234: verbose = 0; 235: continue; 236: 237: case DEBUGSW: 238: debug++; 239: continue; 240: } 241: 242: switch (argp - (argv + 1)) { 243: case 1: 244: addr = cp; 245: break; 246: 247: case 2: 248: info = cp; 249: break; 250: 251: case 3: 252: sender = cp; 253: break; 254: } 255: } 256: 257: /* */ 258: 259: if (addr == NULL) 260: addr = getusr (); 261: if (user == NULL) 262: user = (cp = index (addr, '.')) ? ++cp : addr; 263: if ((pw = getpwnam (user)) == NULL) 264: adios (NULLCP, "no such local user as %s", user); 265: 266: if (chdir (pw -> pw_dir) == NOTOK) 267: (void) chdir ("/"); 268: (void) umask (0077); 269: 270: if (geteuid () == 0) { 271: #ifdef BSD41A 272: (void) inigrp (pw -> pw_name, pw -> pw_gid); 273: #endif BSD41A 274: (void) setgid (pw -> pw_gid); 275: #ifdef BSD42 276: (void) initgroups (pw -> pw_name, pw -> pw_gid); 277: #endif BSD42 278: (void) setuid (pw -> pw_uid); 279: } 280: 281: if (info == NULL) 282: info = ""; 283: 284: setbuf (stdin, NULLCP); 285: 286: if (file == NULL) { 287: if ((fd = copyfile (fileno (stdin), file = tmpfil, 1)) == NOTOK) 288: adios (NULLCP, "unable to create temporary file"); 289: if (debug) 290: fprintf (stderr, "temporary file \"%s\" selected\n", tmpfil); 291: else 292: (void) unlink (tmpfil); 293: if ((fp = fdopen (fd, "r+")) == NULL) 294: adios (NULLCP, "unable to access temporary file"); 295: } 296: else 297: fd = fileno (stdin); 298: 299: from[0] = NULL; 300: if (sender == NULL) 301: copyinfo (fp, from); 302: 303: 304: if (mbox == NULL) { 305: (void) sprintf (mailbox, "%s/%s", 306: mmdfldir[0] ? mmdfldir : pw -> pw_dir, 307: mmdflfil[0] ? mmdflfil : pw -> pw_name); 308: mbox = mailbox; 309: } 310: if (home == NULL) 311: home = pw -> pw_dir; 312: 313: if ((now = dtwstime ()) == NULL) 314: adios (NULLCP, "unable to ascertain local time"); 315: (void) sprintf (ddate, "Delivery-Date: %s\n", dtimenow ()); 316: 317: if (debug) { 318: fprintf (stderr, "addr=\"%s\" user=\"%s\" info=\"%s\" file=\"%s\"\n", 319: addr, user, info, file); 320: fprintf (stderr, "sender=\"%s\" mbox=\"%s\" home=\"%s\" from=\"%s\"\n", 321: sender, mbox, home, from); 322: fprintf (stderr, "ddate=\"%s\" now=%02d:%02d\n", 323: ddate, now -> tw_hour, now -> tw_min); 324: } 325: 326: done (localmail (fd, from, mdlvr) != NOTOK ? RCV_MOK : RCV_MBX); 327: } 328: 329: /* */ 330: 331: static int localmail (fd, from, mdlvr) 332: int fd; 333: char *from, 334: *mdlvr; 335: { 336: if (usr_delivery (fd, mdlvr ? mdlvr : ".maildelivery", 0) != NOTOK) 337: return OK; 338: 339: if (usr_delivery (fd, maildelivery, 1) != NOTOK) 340: return OK; 341: 342: #ifdef notdef 343: if (verbose) 344: printf ("(invoking hook)\n"); 345: if (usr_hook (fd, mbox) != NOTOK) 346: return OK; 347: #endif notdef 348: 349: if (verbose) 350: printf ("(trying normal delivery)\n"); 351: return usr_file (fd, mbox, from); 352: } 353: 354: /* */ 355: 356: #define matches(a,b) (stringdex (b, a) >= 0) 357: 358: static int usr_delivery (fd, delivery, su) 359: int fd, 360: su; 361: char *delivery; 362: { 363: int i, 364: accept, 365: status, 366: won, 367: vecp; 368: register char *cp, 369: *action, 370: *field, 371: *pattern, 372: *string; 373: char buffer[BUFSIZ], 374: tmpbuf[BUFSIZ], 375: *vec[NVEC]; 376: struct stat st; 377: register struct pair *p; 378: register FILE *fp; 379: 380: if ((fp = fopen (delivery, "r")) == NULL) 381: return NOTOK; 382: if (fstat (fileno (fp), &st) == NOTOK 383: || (st.st_uid != 0 && (su || st.st_uid != pw -> pw_uid)) 384: || st.st_mode & 0022) { 385: if (verbose) { 386: printf ("%s: ownership/modes bad (%d, %d,%d,0%o)\n", 387: delivery, su, pw -> pw_uid, st.st_uid, st.st_mode); 388: (void) fflush (stdout); 389: } 390: return NOTOK; 391: } 392: 393: won = 0; 394: while (fgets (buffer, sizeof buffer, fp) != NULL) { 395: if (*buffer == '#') 396: continue; 397: if (cp = index (buffer, '\n')) 398: *cp = NULL; 399: if ((vecp = split (buffer, vec)) < 5) 400: continue; 401: if (debug) 402: for (i = 0; vec[i]; i++) 403: fprintf (stderr, "vec[%d]: \"%s\"\n", i, vec[i]); 404: 405: field = vec[0]; 406: pattern = vec[1]; 407: action = vec[2]; 408: 409: switch (vec[3][0]) { 410: case '?': 411: if (won) 412: continue; /* else fall */ 413: case 'A': 414: case 'a': 415: accept = 1; 416: break; 417: 418: case 'R': 419: case 'r': 420: default: 421: accept = 0; 422: break; 423: } 424: 425: string = vec[4]; 426: 427: if (vecp > 5) { 428: if (uleq (vec[5], "select")) { 429: if (logged_in () != NOTOK) 430: continue; 431: if (vecp > 7 && timely (vec[6], vec[7]) == NOTOK) 432: continue; 433: } 434: } 435: 436: switch (*field) { 437: case '*': 438: break; 439: 440: case 'd': 441: if (uleq (field, "default")) { 442: if (won) 443: continue; 444: break; 445: } /* else fall */ 446: 447: default: 448: if (!parsed && parse (fd) == NOTOK) { 449: (void) fclose (fp); 450: return NOTOK; 451: } 452: if ((p = lookup (hdrs, field)) == NULL 453: || !matches (p -> p_value, pattern)) 454: continue; 455: break; 456: } 457: 458: switch (*action) { 459: case 'q': 460: if (!uleq (action, "qpipe")) 461: continue; /* else fall */ 462: case '^': 463: expand (tmpbuf, string, fd); 464: if (split (tmpbuf, vec) < 1) 465: continue; 466: status = usr_pipe (fd, tmpbuf, vec[0], vec); 467: break; 468: 469: case 'p': 470: if (!uleq (action, "pipe")) 471: continue; /* else fall */ 472: case '|': 473: vec[2] = "sh"; 474: vec[3] = "-c"; 475: expand (tmpbuf, string, fd); 476: vec[4] = tmpbuf; 477: vec[5] = NULL; 478: status = usr_pipe (fd, tmpbuf, "/bin/sh", vec + 2); 479: break; 480: 481: case 'f': 482: if (!uleq (action, "file")) 483: continue; /* else fall */ 484: case '>': 485: status = usr_file (fd, string, NULLCP); 486: break; 487: 488: case 'd': 489: if (!uleq (action, "destroy")) 490: continue; 491: status = OK; 492: break; 493: } 494: 495: if (accept) { 496: if (status == NOTOK) { 497: won = 0; 498: break; 499: } 500: won++; 501: } 502: } 503: 504: (void) fclose (fp); 505: return (won ? OK : NOTOK); 506: } 507: 508: /* */ 509: 510: #define QUOTE '\\' 511: 512: static int split (cp, vec) 513: char *cp, 514: **vec; 515: { 516: register int i; 517: register char *s; 518: 519: for (i = 0, s = cp; i <= NVEC;) { 520: vec[i] = NULL; 521: while (isspace (*s) || *s == ',') 522: *s++ = NULL; 523: if (*s == NULL) 524: break; 525: 526: if (*s == '"') { 527: for (vec[i++] = ++s; *s != NULL && *s != '"'; s++) 528: if (*s == QUOTE) { 529: if (*++s == '"') 530: (void) strcpy (s - 1, s); 531: s--; 532: } 533: if (*s == '"') 534: *s++ = NULL; 535: continue; 536: } 537: if (*s == QUOTE && *++s != '"') 538: s--; 539: vec[i++] = s++; 540: 541: while (*s != NULL && !isspace (*s) && *s != ',') 542: s++; 543: } 544: vec[i] = NULL; 545: 546: return i; 547: } 548: 549: /* */ 550: 551: static int parse (fd) 552: register int fd; 553: { 554: register int i, 555: state; 556: int fd1; 557: register char *cp, 558: *dp, 559: *lp; 560: char name[NAMESZ], 561: field[BUFSIZ]; 562: register struct pair *p, 563: *q; 564: register FILE *in; 565: 566: if (parsed++) 567: return OK; 568: 569: if ((fd1 = dup (fd)) == NOTOK) 570: return NOTOK; 571: if ((in = fdopen (fd1, "r")) == NULL) { 572: (void) close (fd1); 573: return NOTOK; 574: } 575: rewind (in); 576: 577: if (p = lookup (hdrs, "source")) 578: p -> p_value = getcpy (sender); 579: if (p = lookup (hdrs, "addr")) 580: p -> p_value = getcpy (addr); 581: 582: for (i = 0, state = FLD;;) { 583: switch (state = m_getfld (state, name, field, sizeof field, in)) { 584: case FLD: 585: case FLDEOF: 586: case FLDPLUS: 587: lp = add (field, NULLCP); 588: while (state == FLDPLUS) { 589: state = m_getfld (state, name, field, sizeof field, in); 590: lp = add (field, lp); 591: } 592: for (p = hdrs; p -> p_name; p++) 593: if (uleq (p -> p_name, name)) { 594: if (!(p -> p_flags & P_HID)) { 595: if (cp = p -> p_value) 596: if (p -> p_flags & P_ADR) { 597: dp = cp + strlen (cp) - 1; 598: if (*dp == '\n') 599: *dp = NULL; 600: cp = add (",\n\t", cp); 601: } 602: else 603: cp = add ("\t", cp); 604: p -> p_value = add (lp, cp); 605: } 606: free (lp); 607: break; 608: } 609: if (p -> p_name == NULL && i < NVEC) { 610: p -> p_name = getcpy (name); 611: p -> p_value = lp; 612: p -> p_flags = P_NIL; 613: p++, i++; 614: p -> p_name = NULL; 615: } 616: if (state != FLDEOF) 617: continue; 618: break; 619: 620: case BODY: 621: case BODYEOF: 622: case FILEEOF: 623: break; 624: 625: case LENERR: 626: case FMTERR: 627: advise (NULLCP, "format error in message"); 628: break; 629: 630: default: 631: advise (NULLCP, "internal error"); 632: (void) fclose (in); 633: return NOTOK; 634: } 635: break; 636: } 637: (void) fclose (in); 638: 639: if (p = lookup (vars, "reply-to")) { 640: if ((q = lookup (hdrs, "reply-to")) == NULL || q -> p_value == NULL) 641: q = lookup (hdrs, "from"); 642: p -> p_value = getcpy (q ? q -> p_value : ""); 643: p -> p_flags &= ~P_CHK; 644: if (debug) 645: fprintf (stderr, "vars[%d]: name=\"%s\" value=\"%s\"\n", 646: p - vars, p -> p_name, p -> p_value); 647: } 648: if (debug) 649: for (p = hdrs; p -> p_name; p++) 650: fprintf (stderr, "hdrs[%d]: name=\"%s\" value=\"%s\"\n", 651: p - hdrs, p -> p_name, p -> p_value); 652: 653: return OK; 654: } 655: 656: /* */ 657: 658: #define LPAREN '(' 659: #define RPAREN ')' 660: 661: static expand (s1, s2, fd) 662: register char *s1, 663: *s2; 664: int fd; 665: { 666: register char c, 667: *cp; 668: register struct pair *p; 669: 670: if (!globbed) 671: glob (fd); 672: 673: while (c = *s2++) 674: if (c != '$' || *s2 != LPAREN) 675: *s1++ = c; 676: else { 677: for (cp = ++s2; *s2 && *s2 != RPAREN; s2++) 678: continue; 679: if (*s2 != RPAREN) { 680: s2 = --cp; 681: continue; 682: } 683: *s2++ = NULL; 684: if (p = lookup (vars, cp)) { 685: if (!parsed && (p -> p_flags & P_CHK)) 686: (void) parse (fd); 687: 688: (void) strcpy (s1, p -> p_value); 689: s1 += strlen (s1); 690: } 691: } 692: *s1 = NULL; 693: } 694: 695: /* */ 696: 697: static glob (fd) 698: register int fd; 699: { 700: char buffer[BUFSIZ]; 701: struct stat st; 702: register struct pair *p; 703: 704: if (globbed++) 705: return; 706: 707: if (p = lookup (vars, "sender")) 708: p -> p_value = getcpy (sender); 709: if (p = lookup (vars, "address")) 710: p -> p_value = getcpy (addr); 711: if (p = lookup (vars, "size")) { 712: (void) sprintf (buffer, "%d", 713: fstat (fd, &st) != NOTOK ? (int) st.st_size : 0); 714: p -> p_value = getcpy (buffer); 715: } 716: if (p = lookup (vars, "info")) 717: p -> p_value = getcpy (info); 718: 719: if (debug) 720: for (p = vars; p -> p_name; p++) 721: fprintf (stderr, "vars[%d]: name=\"%s\" value=\"%s\"\n", 722: p - vars, p -> p_name, p -> p_value); 723: } 724: 725: /* */ 726: 727: static struct pair *lookup (pairs, key) 728: register struct pair *pairs; 729: register char *key; 730: { 731: register char *cp; 732: 733: for (; cp = pairs -> p_name; pairs++) 734: if (uleq (cp, key)) 735: return pairs; 736: 737: return NULL; 738: } 739: 740: /* */ 741: 742: static int logged_in () { 743: struct utmp ut; 744: register FILE *uf; 745: 746: if (utmped) 747: return utmped; 748: 749: if ((uf = fopen ("/etc/utmp", "r")) == NULL) 750: return NOTOK; 751: 752: while (fread ((char *) &ut, sizeof ut, 1, uf) == 1) 753: if (ut.ut_name[0] != NULL 754: && strncmp (user, ut.ut_name, sizeof ut.ut_name) == 0) { 755: if (debug) 756: continue; 757: (void) fclose (uf); 758: return (utmped = DONE); 759: } 760: 761: (void) fclose (uf); 762: return (utmped = NOTOK); 763: } 764: 765: 766: static int timely (t1, t2) 767: char *t1, 768: *t2; 769: { 770: #define check(t,a,b) if (t < a || t > b) return NOTOK 771: #define cmpar(h1,m1,h2,m2) if (h1 < h2 || (h1 == h2 && m1 < m2)) return OK 772: 773: int t1hours, 774: t1mins, 775: t2hours, 776: t2mins; 777: 778: if (sscanf (t1, "%d:%d", &t1hours, &t1mins) != 2) 779: return NOTOK; 780: check (t1hours, 0, 23); 781: check (t1mins, 0, 59); 782: 783: if (sscanf (t2, "%d:%d", &t2hours, &t2mins) != 2) 784: return NOTOK; 785: check (t2hours, 0, 23); 786: check (t2mins, 0, 59); 787: 788: cmpar (now -> tw_hour, now -> tw_min, t1hours, t1mins); 789: cmpar (t2hours, t2mins, now -> tw_hour, now -> tw_min); 790: 791: return NOTOK; 792: } 793: 794: /* */ 795: 796: static int usr_file (fd, mailbox, from) 797: int fd; 798: char *mailbox, 799: *from; 800: { 801: int md, 802: mapping; 803: register char *bp; 804: char buffer[BUFSIZ]; 805: 806: if (verbose) 807: printf ("\tdelivering to file \"%s\"", mailbox); 808: if (from && *from) { 809: (void) mbx_uucp (); 810: if (verbose) 811: printf (" (uucp style)"); 812: (void) sprintf (buffer, "%s%s", from, ddate); 813: bp = buffer; 814: mapping = 0; 815: } 816: else { 817: bp = ddate; 818: mapping = 1; 819: } 820: if (verbose) 821: (void) fflush (stdout); 822: 823: if ((md = mbx_open (mailbox, pw -> pw_uid, pw -> pw_gid, m_gmprot ())) 824: == NOTOK) { 825: adorn ("", "unable to open:"); 826: return NOTOK; 827: } 828: 829: (void) lseek (fd, 0L, 0); 830: if (mbx_copy (mailbox, md, fd, mapping, bp, verbose) == NOTOK) { 831: adorn ("", "error writing to:"); 832: return NOTOK; 833: } 834: 835: (void) mbx_close (mailbox, md); 836: if (verbose) { 837: printf (", done.\n"); 838: (void) fflush (stdout); 839: } 840: return OK; 841: } 842: 843: /* */ 844: 845: #ifdef notdef 846: static int usr_hook (fd, mailbox) 847: int fd; 848: char *mailbox; 849: { 850: int i, 851: vecp; 852: char receive[BUFSIZ], 853: tmpfil[BUFSIZ], 854: *vec[NVEC]; 855: 856: if ((fd = copyfile (fd, tmpfil, 0)) == NOTOK) { 857: if (verbose) 858: adorn ("unable to copy message; skipping hook\n"); 859: return NOTOK; 860: } 861: (void) chown (tmpfil, pw -> pw_uid, pw -> pw_gid); 862: 863: vecp = 1; 864: (void) sprintf (receive, "%s/.mh_receive", pw -> pw_dir); 865: switch (access (receive, 01)) { 866: case NOTOK: 867: (void) sprintf (receive, "%s/bin/rcvmail", pw -> pw_dir); 868: if (access (receive, 01) == NOTOK) { 869: (void) unlink (tmpfil); 870: if (verbose) { 871: printf ("\tnot present\n"); 872: (void) fflush (stdout); 873: } 874: return NOTOK; 875: } 876: vec[vecp++] = addr; 877: vec[vecp++] = tmpfil; 878: vec[vecp++] = sender; 879: break; 880: 881: default: 882: vec[vecp++] = tmpfil; 883: vec[vecp++] = mailbox; 884: vec[vecp++] = home; 885: vec[vecp++] = addr; 886: vec[vecp++] = sender; 887: break; 888: } 889: vec[0] = r1bindex (receive, '/'); 890: vec[vecp] = NULL; 891: 892: i = usr_pipe (fd, "rcvmail", receive, vec); 893: (void) unlink (tmpfil); 894: 895: return i; 896: } 897: #endif notdef 898: 899: /* */ 900: 901: static int usr_pipe (fd, cmd, pgm, vec) 902: int fd; 903: char *cmd, 904: *pgm, 905: **vec; 906: { 907: int bytes, 908: i, 909: child_id, 910: status; 911: struct stat st; 912: 913: if (verbose) { 914: printf ("\tdelivering to pipe \"%s\"", cmd); 915: (void) fflush (stdout); 916: } 917: (void) lseek (fd, 0L, 0); 918: 919: for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++) 920: sleep (5); 921: switch (child_id) { 922: case NOTOK: 923: adorn ("fork", "unable to"); 924: return NOTOK; 925: 926: case OK: 927: if (fd != 0) 928: (void) dup2 (fd, 0); 929: (void) freopen ("/dev/null", "w", stdout); 930: (void) freopen ("/dev/null", "w", stderr); 931: if (fd != 3) 932: (void) dup2 (fd, 3); 933: closefds (4); 934: #ifdef TIOCNOTTY 935: if ((fd = open ("/dev/tty", 2)) != NOTOK) { 936: (void) ioctl (fd, TIOCNOTTY, NULLCP); 937: (void) close (fd); 938: } 939: #endif TIOCNOTTY 940: #ifdef BSD42 941: (void) setpgrp (0, getpid ()); 942: #endif BSD42 943: 944: *environ = NULL; 945: (void) putenv ("USER", pw -> pw_name); 946: (void) putenv ("HOME", pw -> pw_dir); 947: (void) putenv ("SHELL", pw -> pw_shell); 948: 949: execvp (pgm, vec); 950: _exit (-1); 951: 952: default: 953: switch (setjmp (myctx)) { 954: case OK: 955: (void) signal (SIGALRM, alrmser); 956: bytes = fstat (fd, &st) != NOTOK ? (int) st.st_size : 100; 957: if (bytes <= 0) 958: bytes = 100; 959: (void) alarm ((unsigned) (bytes * 60 + 300)); 960: 961: status = pidwait (child_id, OK); 962: 963: (void) alarm (0); 964: #ifdef MMDFI 965: if (status == RP_MOK || status == RP_OK) 966: status = 0; 967: #endif MMDFI 968: if (verbose) { 969: if (status == 0) 970: printf (", wins.\n"); 971: else 972: if ((status & 0xff00) == 0xff00) 973: printf (", system error\n"); 974: else 975: (void) pidstatus (status, stdout, ", loses"); 976: (void) fflush (stdout); 977: } 978: return (status == 0 ? OK : NOTOK); 979: 980: default: 981: #ifndef BSD42 982: (void) kill (child_id, SIGKILL); 983: #else BSD42 984: (void) killpg (child_id, SIGKILL); 985: #endif BSD42 986: if (verbose) { 987: printf (", timed-out; terminated\n"); 988: (void) fflush (stdout); 989: } 990: return NOTOK; 991: } 992: } 993: } 994: 995: /* */ 996: 997: /* ARGSUSED */ 998: 999: static int alrmser (i) 1000: int i; 1001: { 1002: longjmp (myctx, DONE); 1003: } 1004: 1005: /* */ 1006: 1007: static copyinfo (fp, from) 1008: register FILE *fp; 1009: char *from; 1010: { 1011: int i; 1012: register char *cp; 1013: static char buffer[BUFSIZ]; 1014: 1015: if (fgets (from, BUFSIZ, fp) == NULL) 1016: adios (NULLCP, "no message"); 1017: 1018: if (strncmp (from, "From ", i = strlen ("From "))) { 1019: rewind (fp); 1020: *from = NULL; 1021: return; 1022: } 1023: 1024: (void) strcpy (buffer, from + i); 1025: if (cp = index (buffer, '\n')) { 1026: *cp = NULL; 1027: cp -= 24; 1028: if (cp < buffer) 1029: cp = buffer; 1030: } 1031: else 1032: cp = buffer; 1033: *cp = NULL; 1034: 1035: for (cp = buffer + strlen (buffer) - 1; cp >= buffer; cp--) 1036: if (isspace (*cp)) 1037: *cp = NULL; 1038: else 1039: break; 1040: sender = buffer; 1041: rewind (fp); 1042: } 1043: 1044: /* */ 1045: 1046: static int copyfile (qd, tmpfil, fold) 1047: int qd, 1048: fold; 1049: register char *tmpfil; 1050: { 1051: register int i, 1052: fd1, 1053: fd2; 1054: char buffer[BUFSIZ]; 1055: register FILE *qfp, 1056: *ffp; 1057: 1058: (void) strcpy (tmpfil, m_tmpfil (invo_name)); 1059: if ((fd1 = creat (tmpfil, 0600)) == NOTOK) 1060: return NOTOK; 1061: (void) close (fd1); 1062: if ((fd1 = open (tmpfil, 2)) == NOTOK) 1063: return NOTOK; 1064: 1065: if (!fold) { 1066: while ((i = read (qd, buffer, sizeof buffer)) > 0) 1067: if (write (fd1, buffer, i) != i) { 1068: you_lose: ; 1069: (void) close (fd1); 1070: (void) unlink (tmpfil); 1071: return NOTOK; 1072: } 1073: if (i == NOTOK) 1074: goto you_lose; 1075: (void) lseek (fd1, 0L, 0); 1076: return fd1; 1077: } 1078: 1079: if ((fd2 = dup (qd)) == NOTOK) { 1080: (void) close (fd1); 1081: return NOTOK; 1082: } 1083: if ((qfp = fdopen (fd2, "r")) == NULL) { 1084: (void) close (fd1); 1085: (void) close (fd2); 1086: return NOTOK; 1087: } 1088: 1089: if ((fd2 = dup (fd1)) == NOTOK) { 1090: (void) close (fd1); 1091: (void) fclose (qfp); 1092: return NOTOK; 1093: } 1094: if ((ffp = fdopen (fd2, "r+")) == NULL) { 1095: (void) close (fd1); 1096: (void) close (fd2); 1097: (void) fclose (qfp); 1098: return NOTOK; 1099: } 1100: 1101: i = strlen ("From "); 1102: while (fgets (buffer, sizeof buffer, qfp)) { 1103: if (!strncmp (buffer, "From ", i)) 1104: putc ('>', ffp); 1105: fputs (buffer, ffp); 1106: if (ferror (ffp)) { 1107: (void) close (fd1); 1108: (void) fclose (ffp); 1109: (void) fclose (qfp); 1110: return NOTOK; 1111: } 1112: } 1113: 1114: (void) fclose (ffp); 1115: if (ferror (qfp)) { 1116: (void) close (fd1); 1117: (void) fclose (qfp); 1118: return NOTOK; 1119: } 1120: (void) fclose (qfp); 1121: 1122: (void) lseek (fd1, 0L, 0); 1123: 1124: return fd1; 1125: } 1126: 1127: /* */ 1128: 1129: /* VARARGS2 */ 1130: 1131: static void adorn (what, fmt, a, b, c, d, e, f) 1132: char *what, 1133: *fmt, 1134: *a, 1135: *b, 1136: *c, 1137: *d, 1138: *e, 1139: *f; 1140: { 1141: char *cp = invo_name; 1142: 1143: if (!verbose) 1144: return; 1145: printf (", "); 1146: 1147: invo_name = NULL; 1148: advise (what, fmt, a, b, c, d, e, f); 1149: invo_name = cp; 1150: }