www.nico.schottelius.org/software/cinit/browse_source/cinit-0.3pre6/client/respawn_svc.c
Nico Schottelius 423ba10303 import cinit from unix.schottelius.org
Signed-off-by: Nico Schottelius <nico@ikn.schottelius.org>
2009-09-16 12:53:45 +02:00

99 lines
2.2 KiB
C

/*
* (c) 2005,2006 Nico Schottelius (nico-linux at schottelius.org)
* respawn_svc
* part of cinit
*/
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include "cinit.h"
/* run a service, gets (relative or absolute) path */
pid_t respawn_svc(char *abspath)
{
pid_t pid;
int tmp;
int pipefd[2];
struct sigaction sa;
char delay[PATH_MAX+1];
D_PRINTF(abspath);
if(pipe(pipefd) == -1) {
perror(MSG_ERR_PIPE);
return 0;
}
pid = fork();
if(pid == -1) {
perror(MSG_ERR_FORK);
return 0;
}
/******************** PARENT ********************/
if(pid > 0) {
/* if we read anything, our child succeded */
if( read(pipefd[0],&tmp,sizeof(tmp)) == -1) {
perror(MSG_ERR_IO);
return 0;
}
return pid; /* return watchers pid */
}
/****************** CHILD: Service watcher ********************/
sa.sa_handler = sig_terminate;
sigaction(SIGTERM,&sa,NULL); /* term = kill respawing process */
/* sigterm handler should kill first our watching pid, reset the
pid to 0 and then we'll kill ourselves */
tmp = 1;
if( write(pipefd[1],&tmp,sizeof(tmp)) == -1) {
perror(MSG_ERR_IO);
_exit(1);
}
/* try to read delay into sock */
strcpy(delay,abspath);
strcat(delay,SLASH);
strcat(delay,C_DELAY);
/* reuse sock to specify delay */
sock = -1;
tmp = open(delay,O_RDONLY);
if(tmp != -1) {
pipefd[0] = read(tmp,&delay[0],PATH_MAX);
if(pipefd[0] > 0 && pipefd[0] <= PATH_MAX) {
delay[pipefd[0]] = 0;
sock = atoi(delay);
}
close(tmp);
}
do {
/* exec_svc will set cpid accordingly */
if( ! exec_svc(abspath, CMD_START_SVC) ) {
if(cpid != 0) {
D_PRINTF("sloefen");
sleep(SLEEP_SVC);
D_PRINTF("Zuende geschlafen");
}
}
} while(cpid); /* cpid is reset by sig_terminate() */
/* FIXME: put most code of sig_terminate here, look for no_kill */
/* start off task */
exec_svc(abspath,CMD_STOP_SVC);
D_PRINTF("jetzt weg");
_exit(0);
}