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: }

Defined functions

done defined in line 456; used 7 times
hook defined in line 269; used 1 times
main defined in line 65; never used
process defined in line 206; used 2 times
seekaddr defined in line 386; used 2 times
seeksndr defined in line 354; used 1 times
sigser defined in line 444; used 3 times
st_init defined in line 408; used 1 times
st_update defined in line 424; used 1 times
umhook defined in line 175; used 1 times

Defined variables

myaddr defined in line 50; used 3 times
myhome defined in line 48; used 2 times
mymail defined in line 49; used 9 times
mystat defined in line 51; used 5 times
myuser defined in line 52; used 2 times
snooze defined in line 42; used 2 times
switches defined in line 30; used 3 times
uucp defined in line 44; used 7 times

Defined macros

HELPSW defined in line 34; never used
SLEEPSW defined in line 31; never used
pgrp_ok defined in line 172; used 1 times
Last modified: 1985-12-19
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1428
Valid CSS Valid XHTML 1.0 Strict