Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / uip / RCS / umhook.c,v
1 head    1.4;
2 access;
3 symbols;
4 locks; strict;
5 comment @ * @;
6
7
8 1.4
9 date    93.08.25.17.29.36;      author jromine; state Exp;
10 branches;
11 next    1.3;
12
13 1.3
14 date    92.11.04.01.05.01;      author jromine; state Exp;
15 branches;
16 next    1.2;
17
18 1.2
19 date    92.02.03.16.37.06;      author jromine; state Exp;
20 branches;
21 next    1.1;
22
23 1.1
24 date    92.02.03.16.36.33;      author jromine; state Exp;
25 branches;
26 next    ;
27
28
29 desc
30 @@
31
32
33 1.4
34 log
35 @off_t fixes for BSD44
36 @
37 text
38 @/* umhook.c - one attempt at a rcvmail hook for UUCP mail */
39 #ifndef lint
40 static char ident[] = "@@(#)$Id: umhook.c,v 1.3 1992/11/04 01:05:01 jromine Exp jromine $";
41 #endif  lint
42
43 /* I don't comment my code heavily, so read this...
44
45     You run this program from your .login file.  The invocation is simply
46     "umhook".  The program "detaches" itself and runs unattended until you
47     logout.  Whenever you get UUCP mail (or upto a minute afterwards),
48     umhook will filter your UUCP mail drop to a temporary file.  The mail
49     drop is *NOT* touched beyond this (even the access time remains the
50     same).  For each message that was new in the mail drop, umhook will
51     fork a process to interpret your .maildelivery file.
52
53     The umhook program uses the -ljobs control facility to do two things:
54         - determine when the controlling tty has gone away
55         - kill a child that's run away (the child sets up a process group)
56  */
57
58 #include "../h/mh.h"
59 #include "../zotnet/mf.h"
60 #include <stdio.h>
61 #include "../zotnet/mts.h"
62 #include <pwd.h>
63 #include <signal.h>
64 #include <sys/ioctl.h>
65 #include <sys/types.h>
66 #include <sys/stat.h>
67 #ifdef LOCALE
68 #include        <locale.h>
69 #endif
70
71 /* \f */
72
73 static struct swit switches[] = {
74 #define SLEEPSW 0
75     "sleep seconds", 0,
76
77 #define HELPSW  1
78     "help", 4,
79
80     NULL, NULL
81 };
82
83 /* \f */
84
85 static int  snooze = 60;
86
87 static int  uucp = NOTOK;
88
89 extern char *environ;
90
91 static char myhome[BUFSIZ] = "";
92 static char mymail[BUFSIZ] = "";
93 static char myaddr[BUFSIZ] = "";
94 static char mystat[BUFSIZ] = "";
95 static char myuser[BUFSIZ] = "";
96
97 int     sigser ();
98
99 off_t    lseek ();
100 #ifdef  SYS5
101 #ifndef __STDC__
102 struct passwd  *getpwuid ();
103 #endif /* !__STDC__ */
104 #endif  SYS5
105
106 /* \f */
107
108 /* ARGSUSED */
109
110 main (argc, argv)
111 int     argc;
112 char  **argv;
113 {
114     char   *cp,
115           **ap,
116           **argp,
117             buf[100],
118            *arguments[MAXARGS];
119     struct passwd  *pw;
120
121 #ifdef LOCALE
122         setlocale(LC_ALL, "");
123 #endif
124     invo_name = r1bindex (argv[0], '/');
125     mts_init (invo_name);
126     if ((cp = m_find (invo_name)) != NULL) {
127         ap = brkstring (cp = getcpy (cp), " ", "\n");
128         ap = copyip (ap, arguments);
129     }
130     else
131         ap = arguments;
132     (void) copyip (argv + 1, ap);
133     argp = arguments;
134
135 /* \f */
136
137     while (cp = *argp++) {
138         if (*cp == '-')
139             switch (smatch (++cp, switches)) {
140                 case AMBIGSW: 
141                     ambigsw (cp, switches);
142                     done (1);
143                 case UNKWNSW: 
144                     adios (NULLCP, "-%s unknown", cp);
145                 case HELPSW: 
146                     (void) sprintf (buf, "%s [switches]", invo_name);
147                     help (buf, switches);
148                     done (1);
149
150                 case SLEEPSW: 
151                     if (!(cp = *argp++) || *cp == '-')
152                         adios (NULLCP, "missing argument to %s", argp[-2]);
153                     if ((snooze = atoi (cp)) < 0)
154                         adios (NULLCP, "bad argument %s %s", argp[-2], cp);
155                     continue;
156             }
157         adios (NULLCP, "usage: %s [switches]", invo_name);
158     }
159
160 /* \f */
161
162     if ((pw = getpwuid (getuid ())) == NULL)
163         adios (NULLCP, "you lose big");
164
165     *environ = NULL;
166     (void) m_putenv ("USER", pw -> pw_name);
167     (void) m_putenv ("HOME", pw -> pw_dir);
168     (void) m_putenv ("SHELL", pw -> pw_shell);
169     if (chdir (pw -> pw_dir) == NOTOK)
170         (void) chdir ("/");
171     (void) umask (0077);
172
173     if (geteuid () == 0) {
174 #ifdef  BSD41A
175         (void) inigrp (pw -> pw_name, pw -> pw_gid);
176 #endif  BSD41A
177         (void) setgid (pw -> pw_gid);
178 #ifdef  BSD42
179         (void) initgroups (pw -> pw_name, pw -> pw_gid);
180 #endif  BSD42
181         (void) setuid (pw -> pw_uid);
182     }
183
184     (void) sprintf (mymail, "%s/%s",
185             uucpldir[0] ? uucpldir : pw -> pw_dir,
186             uucplfil[0] ? uucplfil : pw -> pw_name);
187     (void) strcpy (myuser, pw -> pw_name);
188     (void) sprintf (myaddr, "%s@@%s", pw -> pw_name, LocalName ());
189     (void) strcpy (myhome, pw -> pw_dir);
190     (void) sprintf (mystat, ".%s_%d", invo_name, pw -> pw_uid);
191
192     if (access (slocalproc, 1) == NOTOK)
193         adios (slocalproc, "unable to execute");
194
195     closefds (fileno (stderr) + 1);
196
197     (void) signal (SIGINT, SIG_IGN);
198     (void) signal (SIGHUP, sigser);
199     (void) signal (SIGQUIT, SIG_IGN);
200     (void) signal (SIGTERM, sigser);
201
202     switch (fork ()) {
203         case NOTOK: 
204         case OK: 
205             umhook ();
206             break;
207
208         default: 
209             break;
210     }
211
212     exit (0);
213 }
214
215 /* \f */
216
217 #ifndef TIOCGPGRP
218 #define pgrp_ok(pg)     1
219 #else   TIOCGPGRP
220 #define pgrp_ok(pg)     (ioctl (2, TIOCGPGRP, (char *) &pg) != NOTOK)
221 #endif  TIOCGPGRP
222
223 static  umhook () {
224     int     pg;
225     struct stat st1,
226                 st2;
227
228     st_init (&st1);
229
230     for (; pgrp_ok (pg);) {
231         if (stat (mymail, &st2) == NOTOK) {
232             st2.st_ino = (ino_t) 0;
233             st2.st_size = (off_t) 0;
234             st2.st_mtime = (time_t) 0;
235         }
236         else
237             if (st1.st_mtime != st2.st_mtime)
238                 if (st1.st_ino != st2.st_ino)
239                     process ((off_t) 0, &st2);
240                 else
241                     if (st1.st_size < st2.st_size)
242                         process (st1.st_size, &st2);
243
244         st1.st_ino = st2.st_ino;
245         st1.st_size = st2.st_size;
246         st1.st_mtime = st2.st_mtime;
247
248         sleep ((unsigned) snooze);
249     }
250 }
251
252 /* \f */
253
254 static  process (offset, st)
255 off_t offset;
256 struct stat *st;
257 {
258     int     td1,
259             td2;
260     time_t timep[2];
261     char    tmpfil[BUFSIZ];
262     register FILE *fp;
263
264     if ((uucp = lkopen (mymail, 0)) == NOTOK)
265         adios (NULLCP, "unable to lock and open %s", mymail);
266     if (lseek (uucp, (off_t) offset, 0) == (off_t) NOTOK)
267         adios (mymail, "unable to position to %ld offset on", (long) offset);
268
269     (void) strcpy (tmpfil, m_tmpfil (invo_name));
270     if ((td1 = creat (tmpfil, TMPMODE)) == NOTOK)
271         adios (tmpfil, "unable to create");
272     (void) close (td1);
273
274     if ((td1 = open (tmpfil, 2)) == NOTOK)
275         adios (tmpfil, "unable to open");
276     (void) unlink (tmpfil);
277     if ((td2 = dup (td1)) == NOTOK)
278         adios ("file descriptor", "unable to dup");
279
280     switch (uucp2mmdf (uucp, td1, FALSE)) {
281         case MFPRM: 
282             adios (NULLCP, "internal error while filtering UUCP mail");
283
284         case MFSIO: 
285             adios (NULLCP, "no free file pointers");
286
287         case MFERR: 
288             adios ("UUCP mail", "i/o error while filtering");
289
290         case MFOK: 
291         case MFROM: 
292         case MFHDR: 
293         case MFTXT: 
294             timep[0] = st -> st_atime;
295             timep[1] = st -> st_mtime;
296             utime (mymail, timep);
297             st_update (st);
298             break;
299     }
300     (void) lkclose (uucp, mymail), uucp = NOTOK;
301
302 /* \f */
303
304     (void) close (td1);
305
306     (void) lseek (td2, (off_t)0, 0);
307     if ((fp = fdopen (td2, "r")) == NULL)
308         adios (NULLCP, "no free file pointers");
309
310     while (hook (fp))
311         continue;
312     (void) fclose (fp);
313 }
314
315 /* \f */
316
317 static int  hook (in)
318 register FILE *in;
319 {
320     int     child_id,
321             done,
322             fd1,
323             fd2,
324             i;
325     char    buffer[BUFSIZ],
326             mysndr[BUFSIZ],
327             myfile[BUFSIZ];
328     register FILE *out;
329
330     if (fgets (buffer, sizeof buffer, in) == NULL)
331         return FALSE;
332
333 /* should insist on isdlm1 (buffer) here... */
334
335     (void) strcpy (myfile, m_tmpfil (invo_name));
336     if ((fd1 = creat (myfile, TMPMODE)) == NOTOK)
337         adios (myfile, "unable to create");
338     (void) close (fd1);
339
340     if ((fd1 = open (myfile, 2)) == NOTOK)
341         adios (myfile, "unable to open");
342     (void) unlink (myfile);
343     if ((fd2 = dup (fd1)) == NOTOK)
344         adios ("file descriptor", "unable to dup");
345
346     if ((out = fdopen (fd1, "w")) == NULL)
347         adios (NULLCP, "no free file pointers");
348
349     for (done = TRUE;;) {
350         if (fgets (buffer, sizeof buffer, in) == NULL)
351             break;              /* should be error */
352         if (done && isdlm2 (buffer))
353             break;
354         done = buffer[strlen (buffer) - 1] == '\n';
355         fputs (buffer, out);
356     }
357     (void) fclose (out);
358
359     (void) lseek (fd2, (off_t)0, 0);
360     seeksndr (fd2, mysndr);
361
362 /* \f */
363
364     switch (child_id = fork ()) {
365         case NOTOK: 
366             adios ("fork", "unable to");/* NOTREACHED */
367
368         case OK: 
369             (void) lseek (fd2, (off_t)0, 0);
370             if (fd2 != 0)
371                 (void) dup2 (fd2, 0);
372             (void) freopen ("/dev/null", "w", stdout);
373             (void) freopen ("/dev/null", "w", stderr);
374             if (fd2 != 3)
375                 (void) dup2 (fd2, 3);
376             closefds (4);
377 #ifdef  TIOCNOTTY
378             if ((i = open ("/dev/tty", 2)) != NOTOK) {
379                 (void) ioctl (i, TIOCNOTTY, NULLCP);
380                 (void) close (i);
381             }
382 #endif  TIOCNOTTY
383 #ifdef  BSD42
384             (void) setpgrp (0, getpid ());
385 #endif  BSD42
386
387             execlp (slocalproc, r1bindex (slocalproc, '/'),
388                     "-file", myfile, "-mailbox", mymail,
389                     "-home", myhome, "-addr", myaddr,
390                     "-user", myuser, "-sender", mysndr, NULLCP);
391             adios (slocalproc, "unable to exec");/* NOTREACHED */
392
393         default: 
394             (void) close (fd2);
395             (void) pidwait (child_id, OK);
396             return TRUE;
397     }
398 }
399
400 /* \f */
401
402 static  seeksndr (fd1, mysndr)
403 int     fd1;
404 char   *mysndr;
405 {
406     int     fd2;
407     char   *bp,
408            *hp,
409             from[BUFSIZ],
410             sender[BUFSIZ];
411     register FILE *in;
412
413     if ((fd2 = dup (fd1)) == NOTOK)
414         adios ("file descriptor", "unable to dup");
415     if ((in = fdopen (fd2, "r")) == NULL)
416         adios (NULLCP, "no free file pointers");
417
418     for (from[0] = sender[0] = NULL; mfgets (in, &hp) != DONE;)
419         if ((bp = index (hp, ':')) != NULL) {
420             *bp++ = NULL;
421             if (lequal (hp, "From"))
422                 seekaddr (from, bp);
423             else
424                 if (lequal (hp, "Sender"))
425                     seekaddr (sender, bp);
426         }
427     (void) fclose (in);
428
429     (void) strcpy (mysndr, sender[0] ? sender : from[0] ? from : myaddr);
430 }
431
432 /* \f */
433
434 static  seekaddr (addr, bp)
435 char   *addr,
436        *bp;
437 {
438     struct adrx *adrxp;
439
440     if ((adrxp = seekadrx (bp)) == NULL)
441         return;
442     if (adrxp -> err || !adrxp -> mbox)
443         return;
444
445     if (adrxp -> host)
446         (void) sprintf (addr, "%s@@%s", adrxp -> mbox, adrxp -> host);
447     else
448         (void) strcpy (addr, adrxp -> mbox);
449
450     while (seekadrx (NULLCP))
451         continue;
452 }
453
454 /* \f */
455
456 static st_init(st)
457 struct stat *st;
458 {
459     int     fd;
460
461     if ((fd = open (mystat, 0)) == NOTOK
462             || read (fd, (char *) st, sizeof *st) != (sizeof *st)) {
463         st -> st_ino = (ino_t) 0;
464         st -> st_size = (off_t) 0;
465         st -> st_mtime = (time_t) 0;
466     }
467     if (fd != NOTOK)
468         (void) close (fd);
469 }
470
471
472 static st_update(st)
473 struct stat *st;
474 {
475     static int  fd = NOTOK;
476
477     if (fd == NOTOK
478             && (fd = creat (mystat, TMPMODE)) == NOTOK)
479         adios (mystat, "unable to write");
480
481     (void) lseek (fd, (off_t)0, 0);
482     if (write (fd, (char *) st, sizeof *st) != (sizeof *st))
483         adios (mystat, "error writing");
484 }
485
486 /* \f */
487
488 #ifdef  BSD42
489 /* ARGSUSED */
490 #endif  BSD42
491
492 static int  sigser (sig)
493 int     sig;
494 {
495 #ifndef BSD42
496     (void) signal (sig, SIG_IGN);
497 #endif  BSD42
498
499     done (1);
500 }
501
502 /* \f */
503
504 void    done (status)
505 int     status;
506 {
507     (void) lkclose (uucp, mymail), uucp = NOTOK;
508     exit (status);
509 }
510 @
511
512
513 1.3
514 log
515 @LOCALE
516 putenv
517 @
518 text
519 @d3 1
520 a3 1
521 static char ident[] = "@@(#)$Id: umhook.c,v 1.2 1992/02/03 16:37:06 jromine Exp jromine $";
522 d62 1
523 a62 1
524 long    lseek ();
525 d229 2
526 a230 2
527     if (lseek (uucp, (long) offset, 0) == (long) NOTOK)
528         adios (mymail, "unable to position to %ld offset on", offset);
529 d269 1
530 a269 1
531     (void) lseek (td2, 0L, 0);
532 d322 1
533 a322 1
534     (void) lseek (fd2, 0L, 0);
535 d332 1
536 a332 1
537             (void) lseek (fd2, 0L, 0);
538 d444 1
539 a444 1
540     (void) lseek (fd, 0L, 0);
541 @
542
543
544 1.2
545 log
546 @fix
547 @
548 text
549 @d3 1
550 a3 1
551 static char ident[] = "@@(#)$Id: scan.c,v 1.10 1992/01/31 22:26:24 jromine Exp $";
552 d30 3
553 d84 3
554 d129 3
555 a131 3
556     (void) putenv ("USER", pw -> pw_name);
557     (void) putenv ("HOME", pw -> pw_dir);
558     (void) putenv ("SHELL", pw -> pw_shell);
559 @
560
561
562 1.1
563 log
564 @Initial revision
565 @
566 text
567 @d2 3
568 d61 1
569 d63 1
570 @