]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/uip/umhook.c
sbr/mts.c: Delete mmdlm2; use same-valued mmdlm1 instead.
[nmh] / docs / historical / mh-6.8.5 / uip / umhook.c
1 /* umhook.c - one attempt at a rcvmail hook for UUCP mail */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: umhook.c,v 1.4 1993/08/25 17:29:36 jromine Exp $";
4 #endif lint
5
6 /* I don't comment my code heavily, so read this...
7
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.
15
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)
19 */
20
21 #include "../h/mh.h"
22 #include "../zotnet/mf.h"
23 #include <stdio.h>
24 #include "../zotnet/mts.h"
25 #include <pwd.h>
26 #include <signal.h>
27 #include <sys/ioctl.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #ifdef LOCALE
31 #include <locale.h>
32 #endif
33
34 /* \f */
35
36 static struct swit switches[] = {
37 #define SLEEPSW 0
38 "sleep seconds", 0,
39
40 #define HELPSW 1
41 "help", 4,
42
43 NULL, NULL
44 };
45
46 /* \f */
47
48 static int snooze = 60;
49
50 static int uucp = NOTOK;
51
52 extern char *environ;
53
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] = "";
59
60 int sigser ();
61
62 off_t lseek ();
63 #ifdef SYS5
64 #ifndef __STDC__
65 struct passwd *getpwuid ();
66 #endif /* !__STDC__ */
67 #endif SYS5
68
69 /* \f */
70
71 /* ARGSUSED */
72
73 main (argc, argv)
74 int argc;
75 char **argv;
76 {
77 char *cp,
78 **ap,
79 **argp,
80 buf[100],
81 *arguments[MAXARGS];
82 struct passwd *pw;
83
84 #ifdef LOCALE
85 setlocale(LC_ALL, "");
86 #endif
87 invo_name = r1bindex (argv[0], '/');
88 mts_init (invo_name);
89 if ((cp = m_find (invo_name)) != NULL) {
90 ap = brkstring (cp = getcpy (cp), " ", "\n");
91 ap = copyip (ap, arguments);
92 }
93 else
94 ap = arguments;
95 (void) copyip (argv + 1, ap);
96 argp = arguments;
97
98 /* \f */
99
100 while (cp = *argp++) {
101 if (*cp == '-')
102 switch (smatch (++cp, switches)) {
103 case AMBIGSW:
104 ambigsw (cp, switches);
105 done (1);
106 case UNKWNSW:
107 adios (NULLCP, "-%s unknown", cp);
108 case HELPSW:
109 (void) sprintf (buf, "%s [switches]", invo_name);
110 help (buf, switches);
111 done (1);
112
113 case SLEEPSW:
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);
118 continue;
119 }
120 adios (NULLCP, "usage: %s [switches]", invo_name);
121 }
122
123 /* \f */
124
125 if ((pw = getpwuid (getuid ())) == NULL)
126 adios (NULLCP, "you lose big");
127
128 *environ = NULL;
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)
133 (void) chdir ("/");
134 (void) umask (0077);
135
136 if (geteuid () == 0) {
137 #ifdef BSD41A
138 (void) inigrp (pw -> pw_name, pw -> pw_gid);
139 #endif BSD41A
140 (void) setgid (pw -> pw_gid);
141 #ifdef BSD42
142 (void) initgroups (pw -> pw_name, pw -> pw_gid);
143 #endif BSD42
144 (void) setuid (pw -> pw_uid);
145 }
146
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);
154
155 if (access (slocalproc, 1) == NOTOK)
156 adios (slocalproc, "unable to execute");
157
158 closefds (fileno (stderr) + 1);
159
160 (void) signal (SIGINT, SIG_IGN);
161 (void) signal (SIGHUP, sigser);
162 (void) signal (SIGQUIT, SIG_IGN);
163 (void) signal (SIGTERM, sigser);
164
165 switch (fork ()) {
166 case NOTOK:
167 case OK:
168 umhook ();
169 break;
170
171 default:
172 break;
173 }
174
175 exit (0);
176 }
177
178 /* \f */
179
180 #ifndef TIOCGPGRP
181 #define pgrp_ok(pg) 1
182 #else TIOCGPGRP
183 #define pgrp_ok(pg) (ioctl (2, TIOCGPGRP, (char *) &pg) != NOTOK)
184 #endif TIOCGPGRP
185
186 static umhook () {
187 int pg;
188 struct stat st1,
189 st2;
190
191 st_init (&st1);
192
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;
198 }
199 else
200 if (st1.st_mtime != st2.st_mtime)
201 if (st1.st_ino != st2.st_ino)
202 process ((off_t) 0, &st2);
203 else
204 if (st1.st_size < st2.st_size)
205 process (st1.st_size, &st2);
206
207 st1.st_ino = st2.st_ino;
208 st1.st_size = st2.st_size;
209 st1.st_mtime = st2.st_mtime;
210
211 sleep ((unsigned) snooze);
212 }
213 }
214
215 /* \f */
216
217 static process (offset, st)
218 off_t offset;
219 struct stat *st;
220 {
221 int td1,
222 td2;
223 time_t timep[2];
224 char tmpfil[BUFSIZ];
225 register FILE *fp;
226
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);
231
232 (void) strcpy (tmpfil, m_tmpfil (invo_name));
233 if ((td1 = creat (tmpfil, TMPMODE)) == NOTOK)
234 adios (tmpfil, "unable to create");
235 (void) close (td1);
236
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");
242
243 switch (uucp2mmdf (uucp, td1, FALSE)) {
244 case MFPRM:
245 adios (NULLCP, "internal error while filtering UUCP mail");
246
247 case MFSIO:
248 adios (NULLCP, "no free file pointers");
249
250 case MFERR:
251 adios ("UUCP mail", "i/o error while filtering");
252
253 case MFOK:
254 case MFROM:
255 case MFHDR:
256 case MFTXT:
257 timep[0] = st -> st_atime;
258 timep[1] = st -> st_mtime;
259 utime (mymail, timep);
260 st_update (st);
261 break;
262 }
263 (void) lkclose (uucp, mymail), uucp = NOTOK;
264
265 /* \f */
266
267 (void) close (td1);
268
269 (void) lseek (td2, (off_t)0, 0);
270 if ((fp = fdopen (td2, "r")) == NULL)
271 adios (NULLCP, "no free file pointers");
272
273 while (hook (fp))
274 continue;
275 (void) fclose (fp);
276 }
277
278 /* \f */
279
280 static int hook (in)
281 register FILE *in;
282 {
283 int child_id,
284 done,
285 fd1,
286 fd2,
287 i;
288 char buffer[BUFSIZ],
289 mysndr[BUFSIZ],
290 myfile[BUFSIZ];
291 register FILE *out;
292
293 if (fgets (buffer, sizeof buffer, in) == NULL)
294 return FALSE;
295
296 /* should insist on isdlm1 (buffer) here... */
297
298 (void) strcpy (myfile, m_tmpfil (invo_name));
299 if ((fd1 = creat (myfile, TMPMODE)) == NOTOK)
300 adios (myfile, "unable to create");
301 (void) close (fd1);
302
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");
308
309 if ((out = fdopen (fd1, "w")) == NULL)
310 adios (NULLCP, "no free file pointers");
311
312 for (done = TRUE;;) {
313 if (fgets (buffer, sizeof buffer, in) == NULL)
314 break; /* should be error */
315 if (done && isdlm2 (buffer))
316 break;
317 done = buffer[strlen (buffer) - 1] == '\n';
318 fputs (buffer, out);
319 }
320 (void) fclose (out);
321
322 (void) lseek (fd2, (off_t)0, 0);
323 seeksndr (fd2, mysndr);
324
325 /* \f */
326
327 switch (child_id = fork ()) {
328 case NOTOK:
329 adios ("fork", "unable to");/* NOTREACHED */
330
331 case OK:
332 (void) lseek (fd2, (off_t)0, 0);
333 if (fd2 != 0)
334 (void) dup2 (fd2, 0);
335 (void) freopen ("/dev/null", "w", stdout);
336 (void) freopen ("/dev/null", "w", stderr);
337 if (fd2 != 3)
338 (void) dup2 (fd2, 3);
339 closefds (4);
340 #ifdef TIOCNOTTY
341 if ((i = open ("/dev/tty", 2)) != NOTOK) {
342 (void) ioctl (i, TIOCNOTTY, NULLCP);
343 (void) close (i);
344 }
345 #endif TIOCNOTTY
346 #ifdef BSD42
347 (void) setpgrp (0, getpid ());
348 #endif BSD42
349
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 */
355
356 default:
357 (void) close (fd2);
358 (void) pidwait (child_id, OK);
359 return TRUE;
360 }
361 }
362
363 /* \f */
364
365 static seeksndr (fd1, mysndr)
366 int fd1;
367 char *mysndr;
368 {
369 int fd2;
370 char *bp,
371 *hp,
372 from[BUFSIZ],
373 sender[BUFSIZ];
374 register FILE *in;
375
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");
380
381 for (from[0] = sender[0] = NULL; mfgets (in, &hp) != DONE;)
382 if ((bp = index (hp, ':')) != NULL) {
383 *bp++ = NULL;
384 if (lequal (hp, "From"))
385 seekaddr (from, bp);
386 else
387 if (lequal (hp, "Sender"))
388 seekaddr (sender, bp);
389 }
390 (void) fclose (in);
391
392 (void) strcpy (mysndr, sender[0] ? sender : from[0] ? from : myaddr);
393 }
394
395 /* \f */
396
397 static seekaddr (addr, bp)
398 char *addr,
399 *bp;
400 {
401 struct adrx *adrxp;
402
403 if ((adrxp = seekadrx (bp)) == NULL)
404 return;
405 if (adrxp -> err || !adrxp -> mbox)
406 return;
407
408 if (adrxp -> host)
409 (void) sprintf (addr, "%s@%s", adrxp -> mbox, adrxp -> host);
410 else
411 (void) strcpy (addr, adrxp -> mbox);
412
413 while (seekadrx (NULLCP))
414 continue;
415 }
416
417 /* \f */
418
419 static st_init(st)
420 struct stat *st;
421 {
422 int fd;
423
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;
429 }
430 if (fd != NOTOK)
431 (void) close (fd);
432 }
433
434
435 static st_update(st)
436 struct stat *st;
437 {
438 static int fd = NOTOK;
439
440 if (fd == NOTOK
441 && (fd = creat (mystat, TMPMODE)) == NOTOK)
442 adios (mystat, "unable to write");
443
444 (void) lseek (fd, (off_t)0, 0);
445 if (write (fd, (char *) st, sizeof *st) != (sizeof *st))
446 adios (mystat, "error writing");
447 }
448
449 /* \f */
450
451 #ifdef BSD42
452 /* ARGSUSED */
453 #endif BSD42
454
455 static int 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 /* \f */
466
467 void done (status)
468 int status;
469 {
470 (void) lkclose (uucp, mymail), uucp = NOTOK;
471 exit (status);
472 }