1 /* umhook.c - one attempt at a rcvmail hook for UUCP mail */
3 static char ident[] = "@(#)$Id: umhook.c,v 1.4 1993/08/25 17:29:36 jromine Exp $";
6 /* I don't comment my code heavily, so read this...
8 You run this program from your .login file. The invocation is simply
9 "umhook". The program "detaches" itself and runs unattended until you
10 logout. Whenever you get UUCP mail (or upto a minute afterwards),
11 umhook will filter your UUCP mail drop to a temporary file. The mail
12 drop is *NOT* touched beyond this (even the access time remains the
13 same). For each message that was new in the mail drop, umhook will
14 fork a process to interpret your .maildelivery file.
16 The umhook program uses the -ljobs control facility to do two things:
17 - determine when the controlling tty has gone away
18 - kill a child that's run away (the child sets up a process group)
22 #include "../zotnet/mf.h"
24 #include "../zotnet/mts.h"
27 #include <sys/ioctl.h>
28 #include <sys/types.h>
36 static struct swit switches[] = {
48 static int snooze = 60;
50 static int uucp = NOTOK;
54 static char myhome[BUFSIZ] = "";
55 static char mymail[BUFSIZ] = "";
56 static char myaddr[BUFSIZ] = "";
57 static char mystat[BUFSIZ] = "";
58 static char myuser[BUFSIZ] = "";
65 struct passwd *getpwuid ();
66 #endif /* !__STDC__ */
85 setlocale(LC_ALL, "");
87 invo_name = r1bindex (argv[0], '/');
89 if ((cp = m_find (invo_name)) != NULL) {
90 ap = brkstring (cp = getcpy (cp), " ", "\n");
91 ap = copyip (ap, arguments);
95 (void) copyip (argv + 1, ap);
100 while (cp = *argp++) {
102 switch (smatch (++cp, switches)) {
104 ambigsw (cp, switches);
107 adios (NULLCP, "-%s unknown", cp);
109 (void) sprintf (buf, "%s [switches]", invo_name);
110 help (buf, switches);
114 if (!(cp = *argp++) || *cp == '-')
115 adios (NULLCP, "missing argument to %s", argp[-2]);
116 if ((snooze = atoi (cp)) < 0)
117 adios (NULLCP, "bad argument %s %s", argp[-2], cp);
120 adios (NULLCP, "usage: %s [switches]", invo_name);
125 if ((pw = getpwuid (getuid ())) == NULL)
126 adios (NULLCP, "you lose big");
129 (void) m_putenv ("USER", pw -> pw_name);
130 (void) m_putenv ("HOME", pw -> pw_dir);
131 (void) m_putenv ("SHELL", pw -> pw_shell);
132 if (chdir (pw -> pw_dir) == NOTOK)
136 if (geteuid () == 0) {
138 (void) inigrp (pw -> pw_name, pw -> pw_gid);
140 (void) setgid (pw -> pw_gid);
142 (void) initgroups (pw -> pw_name, pw -> pw_gid);
144 (void) setuid (pw -> pw_uid);
147 (void) sprintf (mymail, "%s/%s",
148 uucpldir[0] ? uucpldir : pw -> pw_dir,
149 uucplfil[0] ? uucplfil : pw -> pw_name);
150 (void) strcpy (myuser, pw -> pw_name);
151 (void) sprintf (myaddr, "%s@%s", pw -> pw_name, LocalName ());
152 (void) strcpy (myhome, pw -> pw_dir);
153 (void) sprintf (mystat, ".%s_%d", invo_name, pw -> pw_uid);
155 if (access (slocalproc, 1) == NOTOK)
156 adios (slocalproc, "unable to execute");
158 closefds (fileno (stderr) + 1);
160 (void) signal (SIGINT, SIG_IGN);
161 (void) signal (SIGHUP, sigser);
162 (void) signal (SIGQUIT, SIG_IGN);
163 (void) signal (SIGTERM, sigser);
181 #define pgrp_ok(pg) 1
183 #define pgrp_ok(pg) (ioctl (2, TIOCGPGRP, (char *) &pg) != NOTOK)
193 for (; pgrp_ok (pg);) {
194 if (stat (mymail, &st2) == NOTOK) {
195 st2.st_ino = (ino_t) 0;
196 st2.st_size = (off_t) 0;
197 st2.st_mtime = (time_t) 0;
200 if (st1.st_mtime != st2.st_mtime)
201 if (st1.st_ino != st2.st_ino)
202 process ((off_t) 0, &st2);
204 if (st1.st_size < st2.st_size)
205 process (st1.st_size, &st2);
207 st1.st_ino = st2.st_ino;
208 st1.st_size = st2.st_size;
209 st1.st_mtime = st2.st_mtime;
211 sleep ((unsigned) snooze);
217 static process (offset, st)
227 if ((uucp = lkopen (mymail, 0)) == NOTOK)
228 adios (NULLCP, "unable to lock and open %s", mymail);
229 if (lseek (uucp, (off_t) offset, 0) == (off_t) NOTOK)
230 adios (mymail, "unable to position to %ld offset on", (long) offset);
232 (void) strcpy (tmpfil, m_tmpfil (invo_name));
233 if ((td1 = creat (tmpfil, TMPMODE)) == NOTOK)
234 adios (tmpfil, "unable to create");
237 if ((td1 = open (tmpfil, 2)) == NOTOK)
238 adios (tmpfil, "unable to open");
239 (void) unlink (tmpfil);
240 if ((td2 = dup (td1)) == NOTOK)
241 adios ("file descriptor", "unable to dup");
243 switch (uucp2mmdf (uucp, td1, FALSE)) {
245 adios (NULLCP, "internal error while filtering UUCP mail");
248 adios (NULLCP, "no free file pointers");
251 adios ("UUCP mail", "i/o error while filtering");
257 timep[0] = st -> st_atime;
258 timep[1] = st -> st_mtime;
259 utime (mymail, timep);
263 (void) lkclose (uucp, mymail), uucp = NOTOK;
269 (void) lseek (td2, (off_t)0, 0);
270 if ((fp = fdopen (td2, "r")) == NULL)
271 adios (NULLCP, "no free file pointers");
293 if (fgets (buffer, sizeof buffer, in) == NULL)
296 /* should insist on isdlm1 (buffer) here... */
298 (void) strcpy (myfile, m_tmpfil (invo_name));
299 if ((fd1 = creat (myfile, TMPMODE)) == NOTOK)
300 adios (myfile, "unable to create");
303 if ((fd1 = open (myfile, 2)) == NOTOK)
304 adios (myfile, "unable to open");
305 (void) unlink (myfile);
306 if ((fd2 = dup (fd1)) == NOTOK)
307 adios ("file descriptor", "unable to dup");
309 if ((out = fdopen (fd1, "w")) == NULL)
310 adios (NULLCP, "no free file pointers");
312 for (done = TRUE;;) {
313 if (fgets (buffer, sizeof buffer, in) == NULL)
314 break; /* should be error */
315 if (done && isdlm2 (buffer))
317 done = buffer[strlen (buffer) - 1] == '\n';
322 (void) lseek (fd2, (off_t)0, 0);
323 seeksndr (fd2, mysndr);
327 switch (child_id = fork ()) {
329 adios ("fork", "unable to");/* NOTREACHED */
332 (void) lseek (fd2, (off_t)0, 0);
334 (void) dup2 (fd2, 0);
335 (void) freopen ("/dev/null", "w", stdout);
336 (void) freopen ("/dev/null", "w", stderr);
338 (void) dup2 (fd2, 3);
341 if ((i = open ("/dev/tty", 2)) != NOTOK) {
342 (void) ioctl (i, TIOCNOTTY, NULLCP);
347 (void) setpgrp (0, getpid ());
350 execlp (slocalproc, r1bindex (slocalproc, '/'),
351 "-file", myfile, "-mailbox", mymail,
352 "-home", myhome, "-addr", myaddr,
353 "-user", myuser, "-sender", mysndr, NULLCP);
354 adios (slocalproc, "unable to exec");/* NOTREACHED */
358 (void) pidwait (child_id, OK);
365 static seeksndr (fd1, mysndr)
376 if ((fd2 = dup (fd1)) == NOTOK)
377 adios ("file descriptor", "unable to dup");
378 if ((in = fdopen (fd2, "r")) == NULL)
379 adios (NULLCP, "no free file pointers");
381 for (from[0] = sender[0] = NULL; mfgets (in, &hp) != DONE;)
382 if ((bp = index (hp, ':')) != NULL) {
384 if (lequal (hp, "From"))
387 if (lequal (hp, "Sender"))
388 seekaddr (sender, bp);
392 (void) strcpy (mysndr, sender[0] ? sender : from[0] ? from : myaddr);
397 static seekaddr (addr, bp)
403 if ((adrxp = seekadrx (bp)) == NULL)
405 if (adrxp -> err || !adrxp -> mbox)
409 (void) sprintf (addr, "%s@%s", adrxp -> mbox, adrxp -> host);
411 (void) strcpy (addr, adrxp -> mbox);
413 while (seekadrx (NULLCP))
424 if ((fd = open (mystat, 0)) == NOTOK
425 || read (fd, (char *) st, sizeof *st) != (sizeof *st)) {
426 st -> st_ino = (ino_t) 0;
427 st -> st_size = (off_t) 0;
428 st -> st_mtime = (time_t) 0;
438 static int fd = NOTOK;
441 && (fd = creat (mystat, TMPMODE)) == NOTOK)
442 adios (mystat, "unable to write");
444 (void) lseek (fd, (off_t)0, 0);
445 if (write (fd, (char *) st, sizeof *st) != (sizeof *st))
446 adios (mystat, "error writing");
455 static int sigser (sig)
459 (void) signal (sig, SIG_IGN);
470 (void) lkclose (uucp, mymail), uucp = NOTOK;