Annotation of 43BSD/contrib/mh/uip/slocal.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.