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