|
|
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.