whatnow: call external anno(1) instead of internal annotate().
[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         pid_t pid;
72
73         if (getuid() == geteuid())
74                 return (-1);
75
76         switch (pid = fork()) {
77         case -1:
78                 break;
79
80         case 0:
81                 setgid(getgid());
82                 setuid(getuid());
83                 break;
84
85         default:
86                 pidwait(pid, -1);
87                 break;
88         }
89
90         return pid;
91 }