|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.