Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / sbr / m_update.c
1 /* m_update.c - update the profile */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: m_update.c,v 1.7 1992/12/15 00:20:22 jromine Exp $";
4 #endif  lint
5
6 #include "../h/mh.h"
7 #include <stdio.h>
8 #include <signal.h>
9 #ifndef sigmask
10 #define sigmask(s)      (1 << ((s) - 1))
11 #endif  /* not sigmask */
12
13 static int      m_chkids();
14
15 void m_update () {
16     int     action;
17 #ifndef BSD42
18     TYPESIG (*hstat) (), (*istat) (), (*qstat) (), (*tstat) ();
19 #else   /* BSD42 */
20     int     smask;
21 #endif  /* BSD42 */
22     register struct node   *np;
23     FILE * out;
24
25     if (!(ctxflags & CTXMOD))
26         return;
27     ctxflags &= ~CTXMOD;
28
29     if ((action = m_chkids ()) > OK)
30         return;                 /* child did it for us */
31
32 #ifndef BSD42
33     hstat = signal (SIGHUP, SIG_IGN);
34     istat = signal (SIGINT, SIG_IGN);
35     qstat = signal (SIGQUIT, SIG_IGN);
36     tstat = signal (SIGTERM, SIG_IGN);
37 #else   /* BSD42 */
38     smask = sigblock (sigmask (SIGHUP) | sigmask (SIGINT)
39                         | sigmask (SIGQUIT) | sigmask (SIGTERM));
40 #endif  /* BSD42 */
41
42     if ((out = fopen (ctxpath, "w")) == NULL)
43         adios (ctxpath, "unable to write");
44     for (np = m_defs; np; np = np -> n_next)
45         if (np -> n_context)
46             fprintf (out, "%s: %s\n", np -> n_name, np -> n_field);
47     (void) fclose (out);
48
49 #ifndef BSD42
50     (void) signal (SIGHUP, hstat);
51     (void) signal (SIGINT, istat);
52     (void) signal (SIGQUIT, qstat);
53     (void) signal (SIGTERM, tstat);
54 #else   /* BSD42 */
55     (void) sigsetmask (smask);
56 #endif  /* BSD42 */
57     if (action == OK)
58         _exit (0);              /* we are child, time to die */
59 }
60
61 /* \f */
62
63 /* This hack brought to you so we can handle set[ug]id MH programs.  If we
64    return NOTOK, then no fork is made, we update .mh_profile normally, and
65    return to the caller normally.  If we return 0, then the child is
66    executing, .mh_profile is modified after we set our [ug]ids to the norm.
67    If we return > 0, then the parent is executed and .mh_profile has
68    already be modified.  We can just return to the caller immediately. */
69
70
71 static int  m_chkids () {
72     int     i,
73             child_id;
74
75     if (getuid () == geteuid ())
76         return (NOTOK);
77
78     for (i = 0; (child_id = fork ()) == -1 && i < 5; i++)
79         sleep (5);
80     switch (child_id) {
81         case NOTOK:
82             break;
83
84         case OK:
85             (void) setgid (getgid ());
86             (void) setuid (getuid ());
87             break;
88
89         default:
90             (void) pidwait (child_id, NOTOK);
91             break;
92     }
93
94     return child_id;
95 }