|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.