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);
}
|