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