Annotation of 43BSDReno/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:     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.