/* * (c) 2005 Nico Schottelius (nico-linux at schottelius.org) * run_svc * part of cinit */ #include #include #include #include #include #include #include #include #include #include "cinit.h" /* run a service, gets relative path */ int run_svc_new(char *rpath) { int tmp=0, respawn = 0, status, fd, cnt; 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; /* perhaps move this code to cinit-static, so it's constant */ while(tmp < svc_list.process) { printf("%d\n",tmp); if( ! strcmp(rpath,svc_list.svca[tmp].abs_path) ) { printf("Service im Array\n"); return 0; } 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; } /* check for respawn? */ /* fork before chdir */ pid = fork(); if(pid == -1) { printf("ERORERER\n"); return 0; } else if(pid > 0) { /* parent gets child's PID */ /* NOT IF RESPAWN */ if(!respawn) { waitpid(pid, &status, 0); if(WIFEXITED(status)) return RT_PAR_OK; else return RT_PAR_FAIL; } /* else */ /* Was tun, wenn respawn? nochmal forken als beobachter, oder signal? */ } /*********** CHILD EXECUTION HERE ***********/ /* change to service dir */ /* THis saVES US THE OTHER STRCMP!!!!! */ 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, whether we should respawn fixme: much earlier! */ strcpy(pathtmp,pathbuf); strcat(pathtmp,"/"); strcat(pathtmp,C_RESPAWN); /* FIXME: check return values */ if( !stat(pathtmp,&buf) ) respawn = 1; /**** 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 _one_ 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 if already running / ran / currently starting */ /* debug */ getcwd(pathbuf,1024); printf("dir: %s\n",pathbuf); /* check for service dir */ if( stat(path,&buf) ) { printf("no such service: %s\n", path); return 1; } /* check for needs -> forked() */ strcpy(pathbuf,path); strcat(pathbuf,"/"); strcat(pathbuf,C_NEEDS); if( ! stat(pathbuf,&buf) ) { printf("going for %s\n",pathbuf); tmp = fork(); if(tmp == -1) { printf("error ...\n"); exit(1); } else if(tmp == 0) { /* child */ printf("child for run_run_svcs()\n"); run_run_svcs(pathbuf); _exit(0); printf("ZOOOMBIE\n"); } else printf("parent\n"); } /* check for wants -> forked() ? */ strcpy(pathbuf,path); strcat(pathbuf,"/"); strcat(pathbuf,C_WANTS); if( ! stat(pathbuf,&buf) ) { printf("dir gibt es auch: %s\n", pathbuf); run_run_svcs(pathbuf); } /* 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; }