b3f8168bed12c7ec6d6f9ee940c577166c02011f
[mmh] / sbr / context_save.c
1
2 /*
3  * context_save.c -- write out the updated context file
4  *
5  * $Id$
6  */
7
8 #include <h/mh.h>
9 #include <h/signals.h>
10
11 /*
12  * static prototypes
13  */
14 static int m_chkids(void);
15
16
17 void
18 context_save (void)
19 {
20     int action;
21     register struct node *np;
22     FILE *out;
23     sigset_t set, oset;
24
25     if (!(ctxflags & CTXMOD))
26         return;
27     ctxflags &= ~CTXMOD;
28
29     if ((action = m_chkids ()) > 0)
30         return;                 /* child did it for us */
31
32     /* block a few signals */
33     sigemptyset (&set);
34     sigaddset (&set, SIGHUP);
35     sigaddset (&set, SIGINT);
36     sigaddset (&set, SIGQUIT);
37     sigaddset (&set, SIGTERM);
38     SIGPROCMASK (SIG_BLOCK, &set, &oset);
39
40     if (!(out = fopen (ctxpath, "w")))
41         adios (ctxpath, "unable to write");
42     for (np = m_defs; np; np = np->n_next)
43         if (np->n_context)
44             fprintf (out, "%s: %s\n", np->n_name, np->n_field);
45     fclose (out);
46
47     SIGPROCMASK (SIG_SETMASK, &oset, &set); /* reset the signal mask */
48
49     if (action == 0)
50         _exit (0);              /* we are child, time to die */
51 }
52
53 /*
54  * This hack brought to you so we can handle set[ug]id MH programs.
55  * If we return -1, then no fork is made, we update .mh_profile
56  * normally, and return to the caller normally.  If we return 0,
57  * then the child is executing, .mh_profile is modified after
58  * we set our [ug]ids to the norm.  If we return > 0, then the
59  * parent is executed and .mh_profile has already be modified.
60  * We can just return to the caller immediately.
61  */
62
63 static int
64 m_chkids (void)
65 {
66     int i;
67     pid_t pid;
68
69     if (getuid () == geteuid ())
70         return (-1);
71
72     for (i = 0; (pid = fork ()) == -1 && i < 5; i++)
73         sleep (5);
74
75     switch (pid) {
76         case -1:
77             break;
78
79         case 0:
80             setgid (getgid ());
81             setuid (getuid ());
82             break;
83
84         default:
85             pidwait (pid, -1);
86             break;
87     }
88
89     return pid;
90 }