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

unix.superglobalmegacorp.com

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