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: }

Defined functions

adorn defined in line 1131; used 5 times
alrmser defined in line 999; used 2 times
copyfile defined in line 1046; used 2 times
copyinfo defined in line 1007; used 1 times
expand defined in line 661; used 2 times
glob defined in line 697; used 1 times
localmail defined in line 331; used 1 times
logged_in defined in line 742; used 1 times
lookup defined in line 727; used 12 times
main defined in line 162; never used
parse defined in line 551; used 2 times
split defined in line 512; used 2 times
timely defined in line 766; used 1 times
usr_delivery defined in line 358; used 2 times
usr_file defined in line 796; used 2 times
usr_hook defined in line 846; used 1 times
usr_pipe defined in line 901; used 3 times

Defined variables

addr defined in line 80; used 11 times
ddate defined in line 92; used 4 times
debug defined in line 74; used 8 times
file defined in line 83; used 5 times
globbed defined in line 75; used 2 times
hdrs defined in line 115; used 8 times
home defined in line 86; used 6 times
info defined in line 82; used 5 times
mbox defined in line 85; used 7 times
myctx defined in line 97; used 2 times
now defined in line 94; used 7 times
parsed defined in line 76; used 3 times
pw defined in line 89; used 22 times
sender defined in line 84; used 9 times
switches defined in line 41; used 3 times
user defined in line 81; used 7 times
utmped defined in line 77; used 4 times
vars defined in line 135; used 9 times
verbose defined in line 78; used 16 times

Defined struct's

pair defined in line 101; used 18 times

Defined macros

ADDRSW defined in line 42; never used
DEBUGSW defined in line 63; never used
FILESW defined in line 46; never used
HELPSW defined in line 66; never used
HOMESW defined in line 52; never used
LPAREN defined in line 658; used 1 times
MAILSW defined in line 55; never used
MBOXSW defined in line 50; never used
NVEC defined in line 37; used 5 times
NVERBSW defined in line 60; never used
P_ADR defined in line 107; used 12 times
P_CHK defined in line 109; used 3 times
P_HID defined in line 108; used 3 times
P_NIL defined in line 106; used 5 times
QUOTE defined in line 510; used 2 times
RPAREN defined in line 659; used 2 times
SENDSW defined in line 48; never used
USERSW defined in line 44; never used
VERBSW defined in line 58; never used
check defined in line 770; used 4 times
cmpar defined in line 771; used 2 times
matches defined in line 356; used 1 times
Last modified: 1986-02-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3083
Valid CSS Valid XHTML 1.0 Strict