1: /* m_update.c - update the profile */ 2: 3: #include "../h/mh.h" 4: #include <stdio.h> 5: #include <signal.h> 6: 7: 8: void m_update () { 9: int action; 10: int (*hstat) (), (*istat) (), (*qstat) (), (*tstat) (); 11: register struct node *np; 12: FILE * out; 13: 14: if (!(ctxflags & CTXMOD)) 15: return; 16: ctxflags &= ~CTXMOD; 17: 18: if ((action = m_chkids ()) > OK) 19: return; /* child did it for us */ 20: 21: hstat = signal (SIGHUP, SIG_IGN); 22: istat = signal (SIGINT, SIG_IGN); 23: qstat = signal (SIGQUIT, SIG_IGN); 24: tstat = signal (SIGTERM, SIG_IGN); 25: 26: if ((out = fopen (ctxpath, "w")) == NULL) 27: adios (ctxpath, "unable to write"); 28: for (np = m_defs; np; np = np -> n_next) 29: if (np -> n_context) 30: fprintf (out, "%s: %s\n", np -> n_name, np -> n_field); 31: (void) fclose (out); 32: 33: (void) signal (SIGHUP, hstat); 34: (void) signal (SIGINT, istat); 35: (void) signal (SIGQUIT, qstat); 36: (void) signal (SIGTERM, tstat); 37: if (action == OK) 38: _exit (0); /* we are child, time to die */ 39: } 40: 41: /* */ 42: 43: /* This hack brought to you so we can handle set[ug]id MH programs. If we 44: return NOTOK, then no fork is made, we update .mh_profile normally, and 45: return to the caller normally. If we return 0, then the child is 46: executing, .mh_profile is modified after we set our [ug]ids to the norm. 47: If we return > 0, then the parent is executed and .mh_profile has 48: already be modified. We can just return to the caller immediately. */ 49: 50: 51: static int m_chkids () { 52: int i, 53: child_id; 54: 55: if (getuid () == geteuid ()) 56: return (NOTOK); 57: 58: for (i = 0; (child_id = fork ()) == -1 && i < 5; i++) 59: sleep (5); 60: switch (child_id) { 61: case NOTOK: 62: break; 63: 64: case OK: 65: (void) setgid (getgid ()); 66: (void) setuid (getuid ()); 67: break; 68: 69: default: 70: (void) pidwait (child_id, NOTOK); 71: break; 72: } 73: 74: return child_id; 75: }