]> diplodocus.org Git - nmh/blob - sbr/context_save.c
Typecast to get rid of warnings that index into cc[] is a char.
[nmh] / 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 }