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