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

unix.superglobalmegacorp.com

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