297 lines
		
	
	
	
		
			7.6 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
		
		
			
		
	
	
			297 lines
		
	
	
	
		
			7.6 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| 
								 | 
							
								/* 
							 | 
						||
| 
								 | 
							
								 * (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;
							 | 
						||
| 
								 | 
							
								}
							 |