Annotation of 43BSDReno/contrib/mh/uip/umhook.c, revision 1.1.1.1

1.1       root        1: /* umhook.c - one attempt at a rcvmail hook for UUCP mail */
                      2: 
                      3: /* I don't comment my code heavily, so read this...
                      4: 
                      5:     You run this program from your .login file.  The invocation is simply
                      6:     "umhook".  The program "detaches" itself and runs unattended until you
                      7:     logout.  Whenever you get UUCP mail (or upto a minute afterwards),
                      8:     umhook will filter your UUCP mail drop to a temporary file.  The mail
                      9:     drop is *NOT* touched beyond this (even the access time remains the
                     10:     same).  For each message that was new in the mail drop, umhook will
                     11:     fork a process to interpret your .maildelivery file.
                     12: 
                     13:     The umhook program uses the -ljobs control facility to do two things:
                     14:        - determine when the controlling tty has gone away
                     15:        - kill a child that's run away (the child sets up a process group)
                     16:  */
                     17: 
                     18: #include "../h/mh.h"
                     19: #include "../zotnet/mf.h"
                     20: #include <stdio.h>
                     21: #include "../zotnet/mts.h"
                     22: #include <pwd.h>
                     23: #include <signal.h>
                     24: #include <sys/ioctl.h>
                     25: #include <sys/types.h>
                     26: #include <sys/stat.h>
                     27: 
                     28: /*  */
                     29: 
                     30: static struct swit switches[] = {
                     31: #define        SLEEPSW 0
                     32:     "sleep seconds", 0,
                     33: 
                     34: #define        HELPSW  1
                     35:     "help", 4,
                     36: 
                     37:     NULL, NULL
                     38: };
                     39: 
                     40: /*  */
                     41: 
                     42: static int  snooze = 60;
                     43: 
                     44: static int  uucp = NOTOK;
                     45: 
                     46: extern char *environ;
                     47: 
                     48: static char myhome[BUFSIZ] = "";
                     49: static char mymail[BUFSIZ] = "";
                     50: static char myaddr[BUFSIZ] = "";
                     51: static char mystat[BUFSIZ] = "";
                     52: static char myuser[BUFSIZ] = "";
                     53: 
                     54: long    lseek ();
                     55: #ifdef SYS5
                     56: struct passwd  *getpwuid ();
                     57: #endif SYS5
                     58: 
                     59: 
                     60: static void umhook(), process(), seeksndr(), seekaddr(), st_init(),
                     61:     st_update(), done();
                     62: static int hook();
                     63: static SIGDECL sigser();
                     64: 
                     65: /*  */
                     66: 
                     67: /* ARGSUSED */
                     68: 
                     69: main(argc, argv)
                     70:        int argc;
                     71:        char **argv;
                     72: {
                     73:     char   *cp,
                     74:           **ap,
                     75:           **argp,
                     76:             buf[100],
                     77:            *arguments[MAXARGS];
                     78:     struct passwd  *pw;
                     79: 
                     80:     invo_name = r1bindex (argv[0], '/');
                     81:     mts_init (invo_name);
                     82:     if ((cp = m_find (invo_name)) != NULL) {
                     83:        ap = brkstring (cp = getcpy (cp), " ", "\n");
                     84:        ap = copyip (ap, arguments);
                     85:     }
                     86:     else
                     87:        ap = arguments;
                     88:     (void) copyip (argv + 1, ap);
                     89:     argp = arguments;
                     90: 
                     91: /*  */
                     92: 
                     93:     while (cp = *argp++) {
                     94:        if (*cp == '-')
                     95:            switch (smatch (++cp, switches)) {
                     96:                case AMBIGSW:
                     97:                    ambigsw (cp, switches);
                     98:                    done (1);
                     99:                case UNKWNSW:
                    100:                    adios (NULLCP, "-%s unknown", cp);
                    101:                case HELPSW:
                    102:                    (void) sprintf (buf, "%s [switches]", invo_name);
                    103:                    help (buf, switches);
                    104:                    done (1);
                    105: 
                    106:                case SLEEPSW:
                    107:                    if (!(cp = *argp++) || *cp == '-')
                    108:                        adios (NULLCP, "missing argument to %s", argp[-2]);
                    109:                    if ((snooze = atoi (cp)) < 0)
                    110:                        adios (NULLCP, "bad argument %s %s", argp[-2], cp);
                    111:                    continue;
                    112:            }
                    113:        adios (NULLCP, "usage: %s [switches]", invo_name);
                    114:     }
                    115: 
                    116: /*  */
                    117: 
                    118:     if ((pw = getpwuid (getuid ())) == NULL)
                    119:        adios (NULLCP, "you lose big");
                    120: 
                    121:     *environ = NULL;
                    122:     (void) putenv ("USER", pw -> pw_name);
                    123:     (void) putenv ("HOME", pw -> pw_dir);
                    124:     (void) putenv ("SHELL", pw -> pw_shell);
                    125:     if (chdir (pw -> pw_dir) == NOTOK)
                    126:        (void) chdir ("/");
                    127:     (void) umask (0077);
                    128: 
                    129:     if (geteuid () == 0) {
                    130: #ifdef BSD41A
                    131:        (void) inigrp (pw -> pw_name, pw -> pw_gid);
                    132: #endif BSD41A
                    133:        (void) setgid (pw -> pw_gid);
                    134: #ifdef BSD42
                    135:        (void) initgroups (pw -> pw_name, pw -> pw_gid);
                    136: #endif BSD42
                    137:        (void) setuid (pw -> pw_uid);
                    138:     }
                    139: 
                    140:     (void) sprintf (mymail, "%s/%s",
                    141:            uucpldir[0] ? uucpldir : pw -> pw_dir,
                    142:            uucplfil[0] ? uucplfil : pw -> pw_name);
                    143:     (void) strcpy (myuser, pw -> pw_name);
                    144:     (void) sprintf (myaddr, "%s@%s", pw -> pw_name, LocalName ());
                    145:     (void) strcpy (myhome, pw -> pw_dir);
                    146:     (void) sprintf (mystat, ".%s_%d", invo_name, pw -> pw_uid);
                    147: 
                    148:     if (access (slocalproc, 1) == NOTOK)
                    149:        adios (slocalproc, "unable to execute");
                    150: 
                    151:     closefds (fileno (stderr) + 1);
                    152: 
                    153:     (void) signal (SIGINT, SIG_IGN);
                    154:     (void) signal (SIGHUP, sigser);
                    155:     (void) signal (SIGQUIT, SIG_IGN);
                    156:     (void) signal (SIGTERM, sigser);
                    157: 
                    158:     switch (fork ()) {
                    159:        case NOTOK:
                    160:        case OK:
                    161:            umhook ();
                    162:            break;
                    163: 
                    164:        default:
                    165:            break;
                    166:     }
                    167: 
                    168:     exit (0);
                    169: }
                    170: 
                    171: /*  */
                    172: 
                    173: #ifndef        TIOCGPGRP
                    174: #define        pgrp_ok(pg)     1
                    175: #else  TIOCGPGRP
                    176: #define        pgrp_ok(pg)     (ioctl (2, TIOCGPGRP, (char *) &pg) != NOTOK)
                    177: #endif TIOCGPGRP
                    178: 
                    179: static void
                    180: umhook()
                    181: {
                    182:     int     pg;
                    183:     struct stat st1,
                    184:                 st2;
                    185: 
                    186:     st_init (&st1);
                    187: 
                    188:     for (; pgrp_ok (pg);) {
                    189:        if (stat (mymail, &st2) == NOTOK) {
                    190:            st2.st_ino = (ino_t) 0;
                    191:            st2.st_size = (off_t) 0;
                    192:            st2.st_mtime = (time_t) 0;
                    193:        }
                    194:        else
                    195:            if (st1.st_mtime != st2.st_mtime)
                    196:                if (st1.st_ino != st2.st_ino)
                    197:                    process ((off_t) 0, &st2);
                    198:                else
                    199:                    if (st1.st_size < st2.st_size)
                    200:                        process (st1.st_size, &st2);
                    201: 
                    202:        st1.st_ino = st2.st_ino;
                    203:        st1.st_size = st2.st_size;
                    204:        st1.st_mtime = st2.st_mtime;
                    205: 
                    206:        sleep ((unsigned) snooze);
                    207:     }
                    208: }
                    209: 
                    210: /*  */
                    211: 
                    212: static void
                    213: process(offset, st)
                    214:        off_t offset;
                    215:        struct stat *st;
                    216: {
                    217:     int            td1,
                    218:             td2;
                    219:     time_t timep[2];
                    220:     char    tmpfil[BUFSIZ];
                    221:     register FILE *fp;
                    222: 
                    223:     if ((uucp = lkopen (mymail, 0)) == NOTOK)
                    224:        adios (NULLCP, "unable to lock and open %s", mymail);
                    225:     if (lseek (uucp, (long) offset, 0) == (long) NOTOK)
                    226:        adios (mymail, "unable to position to %ld offset on", offset);
                    227: 
                    228:     (void) strcpy (tmpfil, m_tmpfil (invo_name));
                    229:     if ((td1 = creat (tmpfil, TMPMODE)) == NOTOK)
                    230:        adios (tmpfil, "unable to create");
                    231:     (void) close (td1);
                    232: 
                    233:     if ((td1 = open (tmpfil, 2)) == NOTOK)
                    234:        adios (tmpfil, "unable to open");
                    235:     (void) unlink (tmpfil);
                    236:     if ((td2 = dup (td1)) == NOTOK)
                    237:        adios ("file descriptor", "unable to dup");
                    238: 
                    239:     switch (uucp2mmdf (uucp, td1, FALSE)) {
                    240:        case MFPRM:
                    241:            adios (NULLCP, "internal error while filtering UUCP mail");
                    242: 
                    243:        case MFSIO:
                    244:            adios (NULLCP, "no free file pointers");
                    245: 
                    246:        case MFERR:
                    247:            adios ("UUCP mail", "i/o error while filtering");
                    248: 
                    249:        case MFOK:
                    250:        case MFROM:
                    251:        case MFHDR:
                    252:        case MFTXT:
                    253:            timep[0] = st -> st_atime;
                    254:            timep[1] = st -> st_mtime;
                    255:            utime (mymail, timep);
                    256:            st_update (st);
                    257:            break;
                    258:     }
                    259:     (void) lkclose (uucp, mymail), uucp = NOTOK;
                    260: 
                    261: /*  */
                    262: 
                    263:     (void) close (td1);
                    264: 
                    265:     (void) lseek (td2, 0L, 0);
                    266:     if ((fp = fdopen (td2, "r")) == NULL)
                    267:        adios (NULLCP, "no free file pointers");
                    268: 
                    269:     while (hook (fp))
                    270:        continue;
                    271:     (void) fclose (fp);
                    272: }
                    273: 
                    274: /*  */
                    275: 
                    276: static int
                    277: hook(in)
                    278:        register FILE *in;
                    279: {
                    280:     int     child_id,
                    281:             done,
                    282:             fd1,
                    283:             fd2,
                    284:             i;
                    285:     char    buffer[BUFSIZ],
                    286:             mysndr[BUFSIZ],
                    287:             myfile[BUFSIZ];
                    288:     register FILE *out;
                    289: 
                    290:     if (fgets (buffer, sizeof buffer, in) == NULL)
                    291:        return FALSE;
                    292: 
                    293: /* should insist on isdlm1 (buffer) here... */
                    294: 
                    295:     (void) strcpy (myfile, m_tmpfil (invo_name));
                    296:     if ((fd1 = creat (myfile, TMPMODE)) == NOTOK)
                    297:        adios (myfile, "unable to create");
                    298:     (void) close (fd1);
                    299: 
                    300:     if ((fd1 = open (myfile, 2)) == NOTOK)
                    301:        adios (myfile, "unable to open");
                    302:     (void) unlink (myfile);
                    303:     if ((fd2 = dup (fd1)) == NOTOK)
                    304:        adios ("file descriptor", "unable to dup");
                    305: 
                    306:     if ((out = fdopen (fd1, "w")) == NULL)
                    307:        adios (NULLCP, "no free file pointers");
                    308: 
                    309:     for (done = TRUE;;) {
                    310:        if (fgets (buffer, sizeof buffer, in) == NULL)
                    311:            break;              /* should be error */
                    312:        if (done && isdlm2 (buffer))
                    313:            break;
                    314:        done = buffer[strlen (buffer) - 1] == '\n';
                    315:        fputs (buffer, out);
                    316:     }
                    317:     (void) fclose (out);
                    318: 
                    319:     (void) lseek (fd2, 0L, 0);
                    320:     seeksndr (fd2, mysndr);
                    321: 
                    322: /*  */
                    323: 
                    324:     switch (child_id = fork ()) {
                    325:        case NOTOK:
                    326:            adios ("fork", "unable to");/* NOTREACHED */
                    327: 
                    328:        case OK:
                    329:            (void) lseek (fd2, 0L, 0);
                    330:            if (fd2 != 0)
                    331:                (void) dup2 (fd2, 0);
                    332:            (void) freopen ("/dev/null", "w", stdout);
                    333:            (void) freopen ("/dev/null", "w", stderr);
                    334:            if (fd2 != 3)
                    335:                (void) dup2 (fd2, 3);
                    336:            closefds (4);
                    337: #ifdef TIOCNOTTY
                    338:            if ((i = open ("/dev/tty", 2)) != NOTOK) {
                    339:                (void) ioctl (i, TIOCNOTTY, NULLCP);
                    340:                (void) close (i);
                    341:            }
                    342: #endif TIOCNOTTY
                    343: #ifdef BSD42
                    344:            (void) setpgrp (0, getpid ());
                    345: #endif BSD42
                    346: 
                    347:            execlp (slocalproc, r1bindex (slocalproc, '/'),
                    348:                    "-file", myfile, "-mailbox", mymail,
                    349:                    "-home", myhome, "-addr", myaddr,
                    350:                    "-user", myuser, "-sender", mysndr, NULLCP);
                    351:            adios (slocalproc, "unable to exec");/* NOTREACHED */
                    352: 
                    353:        default:
                    354:            (void) close (fd2);
                    355:            (void) pidwait (child_id, OK);
                    356:            return TRUE;
                    357:     }
                    358: }
                    359: 
                    360: /*  */
                    361: 
                    362: static void
                    363: seeksndr(fd1, mysndr)
                    364:        int fd1;
                    365:        char *mysndr;
                    366: {
                    367:     int     fd2;
                    368:     char   *bp,
                    369:            *hp,
                    370:             from[BUFSIZ],
                    371:             sender[BUFSIZ];
                    372:     register FILE *in;
                    373: 
                    374:     if ((fd2 = dup (fd1)) == NOTOK)
                    375:        adios ("file descriptor", "unable to dup");
                    376:     if ((in = fdopen (fd2, "r")) == NULL)
                    377:        adios (NULLCP, "no free file pointers");
                    378: 
                    379:     for (from[0] = sender[0] = NULL; mfgets (in, &hp) != DONE;)
                    380:        if ((bp = index (hp, ':')) != NULL) {
                    381:            *bp++ = NULL;
                    382:            if (lequal (hp, "From"))
                    383:                seekaddr (from, bp);
                    384:            else
                    385:                if (lequal (hp, "Sender"))
                    386:                    seekaddr (sender, bp);
                    387:        }
                    388:     (void) fclose (in);
                    389: 
                    390:     (void) strcpy (mysndr, sender[0] ? sender : from[0] ? from : myaddr);
                    391: }
                    392: 
                    393: /*  */
                    394: 
                    395: static void
                    396: seekaddr(addr, bp)
                    397:        char *addr, *bp;
                    398: {
                    399:     struct adrx *adrxp;
                    400: 
                    401:     if ((adrxp = seekadrx (bp)) == NULL)
                    402:        return;
                    403:     if (adrxp -> err || !adrxp -> mbox)
                    404:        return;
                    405: 
                    406:     if (adrxp -> host)
                    407:        (void) sprintf (addr, "%s@%s", adrxp -> mbox, adrxp -> host);
                    408:     else
                    409:        (void) strcpy (addr, adrxp -> mbox);
                    410: 
                    411:     while (seekadrx (NULLCP))
                    412:        continue;
                    413: }
                    414: 
                    415: /*  */
                    416: 
                    417: static void
                    418: st_init(st)
                    419:        struct stat *st;
                    420: {
                    421:     int     fd;
                    422: 
                    423:     if ((fd = open (mystat, 0)) == NOTOK
                    424:            || read (fd, (char *) st, sizeof *st) != (sizeof *st)) {
                    425:        st -> st_ino = (ino_t) 0;
                    426:        st -> st_size = (off_t) 0;
                    427:        st -> st_mtime = (time_t) 0;
                    428:     }
                    429:     if (fd != NOTOK)
                    430:        (void) close (fd);
                    431: }
                    432: 
                    433: static void
                    434: st_update(st)
                    435:        struct stat *st;
                    436: {
                    437:     static int  fd = NOTOK;
                    438: 
                    439:     if (fd == NOTOK
                    440:            && (fd = creat (mystat, TMPMODE)) == NOTOK)
                    441:        adios (mystat, "unable to write");
                    442: 
                    443:     (void) lseek (fd, 0L, 0);
                    444:     if (write (fd, (char *) st, sizeof *st) != (sizeof *st))
                    445:        adios (mystat, "error writing");
                    446: }
                    447: 
                    448: /*  */
                    449: 
                    450: #ifdef BSD42
                    451: /* ARGSUSED */
                    452: #endif BSD42
                    453: 
                    454: static SIGDECL
                    455: sigser(sig)
                    456:        int sig;
                    457: {
                    458: #ifndef        BSD42
                    459:     (void) signal (sig, SIG_IGN);
                    460: #endif BSD42
                    461: 
                    462:     done (1);
                    463: }
                    464: 
                    465: /*  */
                    466: 
                    467: static void
                    468: done(status)
                    469:        int status;
                    470: {
                    471:     (void) lkclose (uucp, mymail), uucp = NOTOK;
                    472:     exit (status);
                    473: }

unix.superglobalmegacorp.com

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