www.nico.schottelius.org/software/cinit/browse_source/cinit-0.0.6/old/run_svc.c04

298 lines
7.6 KiB
Text
Raw Normal View History

/*
* (c) 2005 Nico Schottelius (nico-linux at schottelius.org)
* run_svc
* part of cinit
*/
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <limits.h>
#include <stdlib.h>
#include <errno.h>
#include <dirent.h>
#include "cinit.h"
/* run a service, gets relative path */
int run_svc_new(char *rpath)
{
int tmp=0, respawn = 0, status, fd, cnt, sid;
int p_com[2];
char pathbuf[PATH_MAX], pathtmp[PATH_MAX]; /* pathtmp = use-it-for-all bitch*/
char **nargv, *sbuf, *p; /* the argv for the executed process */
struct stat buf;
pid_t pid;
/* check if service is already (beeing) started */
if ( (tmp = chk_svc(rpath) ) != ST_NO) return tmp;
/* check whether service exists */
if( stat(rpath,&buf) ) {
printf("Service does not exist %s\n",rpath);
return 0;
} else if( ! S_ISDIR(buf.st_mode) ) {
printf("Service is not a dir (%s)!\n",rpath);
return 0;
}
/* get our own service ID */
sid = add_mod_svc(rpath,ST_TMP);
/* check, whether we should respawn */
strcpy(pathtmp,pathbuf);
strcat(pathtmp,"/");
strcat(pathtmp,C_RESPAWN); /* FIXME: check return values */
if( stat(pathtmp,&buf) == 0) respawn = 1;
/* if respawn, we have to create a pipe to talk with child */
if(respawn) {
if ( pipe(p_com) == -1 )
cerr("pipe failed",RT_PAR_FAIL);
}
/* fork at the beginning and before chdir */
pid = fork();
if( pid == -1 ) cerr("fork failed",RT_PAR_FAIL);
if(pid == -1) {
cerr("fork failed\n", RT_PAR_FAIL);
} else if(pid > 0) { /* parent gets child's PID */
if(respawn) {
/* read the final byte from child */
read(p_com[0],&tmp,1); /* FIXME: check return */
if(tmp == ST_RESPAWN) {
printf("kind sagte, wir respawnenen jetzt\n");
add_mod_svc(rpath,ST_RESPAWN); /* FIXME: search bei sid! */
return RT_PAR_OK;
} else { /* child failed */
printf("kind sagte, respawn kaputt\n");
add_mod_svc(rpath,ST_FAIL); /* FIXME: search bei sid! */
}
} else { /* execute once */
waitpid(pid, &status, 0);
if(WIFEXITED(status)) {
add_mod_svc(rpath,ST_ONCE); /* FIXME: search bei sid! */
return RT_PAR_OK;
} else {
add_mod_svc(rpath,ST_FAIL); /* FIXME: search bei sid! */
return RT_PAR_FAIL;
}
}
}
/* done till here. PARENTS EXECUTION ENDED! */
/*********** CHILD EXECUTION HERE ***********/
/* change to service dir */
if( chdir(rpath) == -1) {
printf("chdir(%s) failed!\n",rpath);
return 1;
}
/* getcwd returns the full service name */
if(getcwd(pathbuf,PATH_MAX) == NULL) return 0;
printf("absolut and current %s\n",pathbuf);
/* check for needs */
/* do we need absolute paths anymore? */
// strcpy(pathbuf,rpath);
// strcat(pathbuf,"/");
strcat(pathtmp,C_NEEDS);
if( ! stat(pathbuf,&buf) ) {
printf("going for %s\n",pathbuf);
pid = fork();
if(tmp == -1) {
cerr("error ...\n", RT_PAR_FAIL);
} else if(tmp == 0) {
printf("child for run_run_svcs()\n");
run_run_svcs(pathbuf);
_exit(0);
}
else
printf("parent\n");
}
/* check for wants -> forked() ? */
strcpy(pathbuf,rpath);
strcat(pathbuf,"/");
strcat(pathbuf,C_WANTS);
if( ! stat(pathbuf,&buf) ) {
printf("dir gibt es auch: %s\n", pathbuf);
run_run_svcs(pathbuf);
}
/**** RETRIEVE REAL BINARY NAME ****/
/* .../run */
strcpy(pathtmp,pathbuf);
strcat(pathtmp,"/");
strcat(pathtmp,C_RUN); /* FIXME: check return values */
/* readlink retrieves real name, if run is a symlink */
if ( (tmp = readlink(C_RUN,pathtmp,PATH_MAX) ) == -1) {
if (errno != EINVAL) cerr("readlinx failed\n",RT_CHLD_FAIL);
/* binary is not a link, copy that to argv0 */
sbuf = (char *) malloc( strlen(pathbuf) + strlen(C_RUN) + 1 );
if(sbuf == NULL) cerr("malloc failed\n",RT_CHLD_FAIL);
strcpy(sbuf,pathbuf);
strcat(pathtmp,"/");
strcat(pathtmp,C_RUN); /* FIXME: check return values */
} else { /* it's a link, copy to sbuf */
sbuf = (char *) malloc( tmp + 1 );
if(sbuf == NULL) cerr("malloc failed\n",RT_CHLD_FAIL);
strncpy(sbuf,pathtmp,tmp);
sbuf[tmp] = '\0';
}
printf("argv0: %s\n",sbuf);
/**** BUILD ARGV ****/
nargv = malloc( sizeof(char *) );
if(nargv == NULL) cerr("malloc failed\n",RT_CHLD_FAIL);
nargv[0] = sbuf;
/**** read params ****/
strcpy(pathtmp,pathbuf);
strcat(pathtmp,"/");
strcat(pathtmp,C_PARAMS);
if( !stat(pathtmp,&buf) ) {
fd = open(pathtmp,O_RDONLY);
if(fd == -1) cerr("open params failed\n",RT_CHLD_FAIL);
sbuf = NULL;
cnt = 0;
/* most likely one round */
while ( (tmp = read(fd,pathtmp,PATH_MAX-1) ) != 0 ) {
if(tmp == -1) cerr("read params failed\n",RT_CHLD_FAIL);
/* STRCHR >> tmp ???? */
/* terminate for strchr - do we really need that? */
pathtmp[PATH_MAX-1] = '\0';
sbuf = realloc(sbuf,cnt + tmp + 1);
if(sbuf == NULL) cerr("realloc failed\n",RT_CHLD_FAIL);
/* copy to temporary buffer */
strncpy(&sbuf[cnt],pathtmp,tmp);
cnt += tmp;
printf("Groesse: %d (%d)\n",tmp,cnt+1);
}
close(fd);
} /* if params */
sbuf[cnt] = '\0';
/* build argv, now really */
/* use the allocated buffer and replace \n with \0 ;-) */
cnt = 1;
// p = sbuf;
while ( *sbuf != '\0' ) {
p = strchr(sbuf,'\n'); /* set p to next \n */
nargv = realloc(nargv,(cnt+1) * sizeof(char *) );
if(nargv == NULL) cerr("malloc failed\n",RT_CHLD_FAIL);
// nargv[cnt] = malloc( sizeof(char *) );
// if(nargv[cnt] == NULL) cerr("malloc failed\n",RT_CHLD_FAIL);
nargv[cnt] = sbuf; /* beginning of argv[cnt] */
*p = '\0'; /* end argv[cnt] */
tmp = p - sbuf;
printf("argv[%d]: %s (%d)\n",cnt,nargv[cnt],tmp);
sbuf = p+1;
cnt++;
}
/* GNAAAAAAAAAA: correct???? */
/* close argv list */
nargv[cnt] = malloc( sizeof(char *) );
if(nargv[cnt] == NULL) cerr("malloc failed\n",RT_CHLD_FAIL);
nargv[cnt] = NULL;
// char *strchr(const char *s, int c);
/* end buffer */
/* get size of argv[n] */
/* run the fscking service */
strcpy(pathtmp,pathbuf);
strcat(pathtmp,"/");
strcat(pathtmp,C_RUN);
printf("Service starten: %s \n", pathtmp);
/* nothing to run, so it's finished */
if( stat(pathtmp,&buf) ) _exit(0);
//execl(pathtmp,pathtmp,"/bin/ls","-l", "/bin/echo");
execv(pathtmp,nargv);
// _exit(1);
/*
if(respawn)
tmp = 0;
execl();
return 1;
*/
}
/***********************************************************************
* run_svc: gets a wants/needs directory
* returns whether the service failed or not
*/
int run_svc(char *path)
{
DIR *d_tmp = NULL;
struct dirent *tdirent;
char *p, pathbuf[1024];
struct stat buf;
int tmp;
/* check for service/run */
strcpy(pathbuf,path);
strcat(pathbuf,"/");
strcat(pathbuf,C_RUN);
d_tmp = opendir(pathbuf);
if(d_tmp == NULL) {
printf("failed to open dir...");
return 0;
}
while( (tdirent = readdir(d_tmp) ) != NULL) {
if (strcmp(tdirent->d_name, ".") == 0 || strcmp(tdirent->d_name, "..") == 0)
continue;
p=tdirent->d_name;
while(*p != '\0') {
write(1,p,1);
p++;
}
write(1,"\n",1);
}
closedir(d_tmp);
return 1;
}