[Wisp-cvs] wisp/users/pisi alterego.c,NONE,1.1
Status: Alpha
Brought to you by:
digg
From: <pi...@us...> - 2003-03-30 19:13:35
|
Update of /cvsroot/wisp/wisp/users/pisi In directory sc8-pr-cvs1:/tmp/cvs-serv5023 Added Files: alterego.c Log Message: alterego hack added --- NEW FILE: alterego.c --- /* alterego.c - keep a process running and handle signals/children as wisp doesn't have correct signaling support and is not SO well suited to run as init - the mother of all processes on a unix system. this is a small wrapper, an "alter ego" or a shadow.. call it whatever, to make a nifty wisp system. this is very linux and wisp and my braindesease specific. it monitors ONE process, restarts it if it quits, and translates a signal to a command that pushes a message into the head of winix message queue. you can send this piece of code two signals: SIGUSR1 - replaces this program with a (posibly) newer version of itself SIGUSR2 - passes /winix/message to winix. this file is public domain, written by a lunatic. */ #include <sys/types.h> #include <sys/wait.h> #include <signal.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #define EGO_LOCATION "/winix/alterego" #define ALTER_EGO_LOCATION "/winix/winix" #define MSG_LOCATION "/winix/msg" pid_t ego; pid_t alter_ego; /* this function replaces the ego with a (possibly) newer one */ int restart_ego (void) { int ego_result; char pid_helper[10]; char *largv[4]; /* we could as well use argv[0] for the executable path.. but hey, who said this code should be nice and perfect? */ snprintf (pid_helper, 9, "%d", alter_ego); largv[0] = EGO_LOCATION; largv[1] = "--alter-ego-pid"; largv[2] = pid_helper; largv[3] = NULL; ego_result = execv (EGO_LOCATION, largv); perror ("Could not restart ego"); return (0); } /* start the alter ego */ int start_alter_ego (void) { int alter_ego_result; char *largv[2]; alter_ego = fork (); if (alter_ego == 0) { /* this is the child, now we exec */ largv[0] = ALTER_EGO_LOCATION; largv[1] = NULL; alter_ego_result = execv (ALTER_EGO_LOCATION, largv); /* we should not get here */ perror ("Could not exec alter ego"); return (0); } else { /* the parent */ if (alter_ego == -1) { perror ("Could not fork alter ego"); return (0); } fprintf (stderr, "Alter ego created: %d\n", alter_ego); return (1); } } int childkiller (void) { pid_t waited_child; int wait_status; while (1) { waited_child = wait (&wait_status); if (waited_child != -1) { if (waited_child == alter_ego) { sleep (1); start_alter_ego (); } } else { if (errno == 10) { printf ("No more children. exiting.\n"); exit (1); } perror ("When waiting"); } } } /* send a message to winix */ int msg_winix (void) { pid_t msg_prgrm; int msg_status; char *largv[4]; largv[0] = MSG_LOCATION; largv[1] = "winix@localhost"; largv[2] = "/winix/message"; largv[3] = NULL; msg_prgrm = fork (); if (msg_prgrm == 0) { /* this is the child, now we exec */ msg_status = execv (MSG_LOCATION, largv); /* we should not get here */ perror ("Could not exec msngr"); return (0); } else { /* the parent */ if (msg_prgrm == -1) { perror ("Could not fork msnger"); return (0); } /* the msg program must be a quickie waitpid(msg_prgrm,NULL,NULL); */ return (1); } } void signal_handler (int signum) { switch (signum) { case SIGUSR1: restart_ego (); break; case SIGUSR2: msg_winix (); break; default: fprintf (stderr, "Don't know how to handle signal %d\n", signum); } } int main (int argc, char *argv[], char *envp[]) { int do_start_alter_ego = 1; struct sigaction act; ego = getpid (); if (ego != 1) { fprintf (stderr, "You should not run this thing as a normal process.\n"); exit (1); } if (argc > 1) { if (!strcmp (argv[1], "--alter-ego-pid")) { do_start_alter_ego = 0; alter_ego = atoi (argv[2]); fprintf (stderr, "Refreshing, alter ego is %d\n", alter_ego); } } if (do_start_alter_ego) start_alter_ego (); /* the most important part - signals */ act.sa_handler = signal_handler; /* block all other signals when handling one */ sigfillset (&act.sa_mask); if (sigaction (SIGUSR1, &act, NULL) < 0) { perror ("sigaction failed"); exit (1); } if (sigaction (SIGUSR2, &act, NULL) < 0) { perror ("sigaction failed"); exit (1); } /* get rid of children */ childkiller (); /* we should never exit from here */ fprintf (stderr, "Sitt lugu, valge mees..."); exit (1); } |