Annotation of 43BSD/contrib/mh/uip/slocal.c, revision 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.