[Initng-svn] r2305 - initng/plugins/simple_launcher

svn at initng.thinktux.net svn at initng.thinktux.net
Fri Dec 2 00:57:25 CET 2005


Author: deac
Date: Fri Dec  2 00:57:23 2005
New Revision: 2305

Modified:
   initng/plugins/simple_launcher/initng_simple_launcher.c
Log:
simple_launcher: exec now allows parameters. exec_args will continue work.

Modified: initng/plugins/simple_launcher/initng_simple_launcher.c
==============================================================================
--- initng/plugins/simple_launcher/initng_simple_launcher.c	(original)
+++ initng/plugins/simple_launcher/initng_simple_launcher.c	Fri Dec  2 00:57:23 2005
@@ -32,6 +32,7 @@
 #include <pwd.h>
 #include <sys/stat.h>
 #include <assert.h>
+#include <errno.h>
 
 #include "../../src/initng_active_db.h"
 #include "../../src/initng_global.h"
@@ -47,212 +48,250 @@
 
 #include "initng_simple_launcher.h"
 
-s_entry EXEC = { "exec", VARIABLE_STRINGS, 4, NULL,
-    "The path and name for an executable."
-};
+s_entry EXEC = { "exec", VARIABLE_STRING, 4, NULL,
+	"The path and name for an executable." };
 s_entry EXEC_ARGS = { "exec_args", VARIABLE_STRING, 9, NULL,
-    "The arguments for the executable."
-};
+	"The arguments for the executable." };
 
-static int simple_exec(process_h * p, active_h * s, char *e, char *ea);
+static int simple_exec(process_h * p, active_h * s, size_t c, char **v);
 
-static int initng_s_launch(active_h * service, process_h * process)
-{
-    char *e = NULL;
-    char *t = NULL;
+#define WHITESPACE( E) ((E)==' '||(E)=='\t'||(E)=='\n'||(E)=='\r'||(E)=='\v')
 
-    assert(service);
-    assert(service->name);
+static void D_argv( char *o, char **argv) {
+	int i;
+	if( argv)
+		for( i = 0; argv[i]; i++)
+			D_( "%s: %s\n", o, argv[i]);
+}
 
+/** Relinks a string to a argv-like string-array.
+ * Something like split_n().
+ * Example: \t  /bin/executeable --ham -flt   --moohoho  lalala
+ *       => \t  /bin/executeable\0--ham\0-flt\0  --moo\0hoho\0 lalala
+ *    argv:     ^[0]              ^[1]   ^[2]    ^[3]   ^[4]   ^[5]
+ *    argc: 6
+ * @author DEac-
+ */
+static char **split_argv( char *e, size_t *argc) {
+	int i = 0;
+	int j = 0;
+	void *b = NULL;
+	char **argv = malloc( sizeof *argv);
+	if( !argv) {
+		F_( "malloc returns NULL: %s\n", strerror( errno));
+		return NULL;
+	}
+	if( !e)
+		return NULL;
+	*argc = 0;
+	for( ; e[i]; i++) {
+		/* till no whitespace... */
+		for( ; WHITESPACE( e[i]); i++);
+		/* begin of a word found, no get the length */
+		for( j = i; e[i] && !WHITESPACE( e[i]); i++);
+		/* whitespaces at the end can be gorgotten */
+		if( j == i)
+			break;
+		/* make argv taller and increase argc */
+		(*argc)++;
+		b = realloc( argv, (1+ *argc)* sizeof *argv);
+		if( !b) {
+			F_( "realloc returns NULL: %s\n", strerror( errno));
+			/* realloc false, clean up */
+			free( argv);
+			return NULL;
+		}
+		argv = b;
+		/* push it to argv */
+		argv[*argc-1] = e+j;
+		if( !e[i])
+			break;
+		/* set the terminating-null at the end of arg */
+		e[i] = 0;
+	}
+	argv[*argc] = NULL;
+	return argv;
+}
 
-    /* WE ARE EXECUTING A START FILE */
-    if (active_db_is_var(&EXEC, process->pt->name, service))
-    {
-        while ((e =
-                active_db_get_next_string_var(&EXEC, process->pt->name,
-                                              service, e)))
-        {
-
-            struct stat test;
-
-            t = fix_variables(e, service);
-            /* 11/20/2005 SaTaN0rX: preliminary support for searching the PATH */
-            /* only search the PATH if this is NOT already an absolute path */
-            if (t[0] != '/')
-            {
-#define MAX_FILENAME 1000
-                char filename[MAX_FILENAME + 3];
-                char *tmp;
-                int tok_len;
-                const char *PATH = getenv("PATH");
-
-                D_("initng_s_launch: %s contains is not absolute path, searching $PATH\n", t);
-                if (!PATH)
-                {
-                    D_("using default path\n");
-                    PATH =
-                        "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin";
-                }
-                D_("PATH determined to be %s\n", PATH);
-                /* no absolute path, so search $PATH */
-                while (PATH && *PATH)
-                {
-                    /* fill filename with '\0's, so that all strings are properly terminated. */
-                    memset(filename, '\0', MAX_FILENAME + 3);
-                    tmp = strchr(PATH, ':');
-                    if (tmp)
-                        tok_len = tmp - PATH;
-                    else
-                    {
-                        tok_len = strlen(PATH);
-                        tmp = (char *) -1;  /* at the end of this loop, PATH will be set to tmp + 1, which is NULL */
-                    }
-                    if (tok_len >= MAX_FILENAME)
-                    {
-                        PATH = tmp + 1;
-                        continue;           /* PATH segement too long; skip over to next one */
-                    }
-
-                    strncpy(filename, PATH, tok_len);
-                    if (filename[tok_len - 1] != '/')
-                    {
-                        filename[tok_len] = '/';
-                    }
-
-                    strncat(filename, t, MAX_FILENAME - tok_len);
-
-                    D_("Trying %s\n", filename);
-                    if (stat(filename, &test) == -1)
-                    {
-                        D_("Stat failed in the inner loop (PATH) failed on %s\n", filename);
-                    }
-                    else if (test.
-                             st_mode & (S_IXOTH | S_IXGRP | S_IXUSR | S_ISVTX
-                                        | S_ISGID | S_ISUID))
-                    {
-                        /* filename is an executable */
-                        D_("Found %s as Executable\n", filename);
-                        /* t is malloced, free it */
-                        free(t);
-                        /* strdup will call malloc */
-                        t = strdup(filename);
-                        break;              /* exit loop */
-                    }
-                    PATH = tmp + 1;
-                }
-                /* end of loop: either thru break above (in this case, t will have an absolute path pointing
-                 * to an executable,
-                 * or thru loop end: in this case, t has the same contents as it had before, and stat will fail */
-            }
-            if (stat(t, &test) == -1)
-            {
-                F_("Stat failed on %s\n", t);
-                free(t);
-                continue;
+/* Completely rewritten function.
+ * Contains old Code from SaTaN0rX and new Code from DEac-.
+ */
+/** Searches for exec in PATH.
+ * 
+ * @author DEac-
+ * @param exec filename, which searched.
+ * @return executeable file with absolute path.\nIf exec was absolute, this will be a pointer to exec.\nOn failure, it will return NULL.
+ */
+static char *expand_exec( char *exec) {
+	if( !exec)
+		return NULL;
+	/* 11/20/2005 SaTaN0rX: preliminary support for searching the PATH
+	 * only search the PATH if this is NOT already an absolute path
+	 */
+	if( exec[0] != '/') {
+		size_t exec_len = strlen( exec);
+		int i = 0;
+		const char *PATH = getenv("PATH");
+
+		D_("initng_s_launch: %s contains is not absolute path, searching $PATH\n", exec);
+		if( !PATH) {
+			D_("using default path\n");
+			PATH = "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin";
+		}
+		D_("PATH determined to be %s\n", PATH);
+
+		for( ; PATH[i]; i++) {
+			char *filename = NULL;
+			int j = 0;
+			struct stat test;
+
+			/* ':' is the delimeter */
+			for( ; PATH[i] == ':'; i++);
+
+			/* now, their's a possible path */
+			for( j = i; PATH[i] && PATH[i] != ':'; i++);
+			if( i == j) /* ... or the end of PATH, nothing found. */
+				return NULL;
+			if( PATH[j] != '/') {
+				F_("PATH-entry without '/' at the begin. Skip.\n");
+				continue;
+			}
+
+			/* create the complete path to a possible file */
+			filename = malloc( exec_len+ i-j +2);
+			if( !filename) {
+				F_( "malloc returns NULL.\n");
+				return NULL;
+			}
+			memcpy( filename, PATH+j, i-j);
+			j = i-j;
+			if( filename[j] != '/')  /* '/' for delimeter path and file */
+				filename[j++] = '/';
+			memcpy( filename+j, exec, exec_len);
+			/* don't forget the terminating-null */
+			filename[exec_len+j] = 0;
+
+			/* now test, if this file exists and it's executeable? */
+			if( stat( filename, &test) == -1)
+				F_( "stat failes on '%s': %s\n", filename, strerror( errno));
+			else if( test.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR |
+						S_ISVTX | S_ISGID | S_ISUID | S_IFREG)) {
+				/* filename is an executable */
+				D_("Found %s as Executable\n", filename);
+				return filename;
+			}
+			free( filename);
+		}
+	} else
+		return exec;
+	F_( "No executeable found\n");
+	return NULL;
+}
 
-            }
+static int initng_s_launch(active_h * service, process_h * process) {
+	int i, j;
+	char *e = NULL;
+	char *t = NULL;
+	char *u = NULL;
+	char **a = NULL;
+	void *b = NULL;
+	size_t argc = 0;
+	size_t c = 0;
+	char **argv = NULL;
+    assert(service);
+    assert(service->name);
 
-            if (simple_exec(process, service, t,
-                            active_db_get_string_var(&EXEC_ARGS,
-                                                     process->pt->name,
-                                                     service)))
-            {
-                free(t);
-                return (TRUE);
+    /* WE ARE EXECUTING A START FILE */
+    if (active_db_is_var(&EXEC, process->pt->name, service)) {
+        while( (e = active_db_get_string_var( &EXEC, process->pt->name, service))) {
+			t = fix_variables( e, service);
+			/* argv-entries are pointer to t[x] */
+			argv = split_argv( t, &argc);
+			if( !argv) {
+				D_( "split_argv returns NULL.\n");
+				free( t);
+				continue;
+			}
+			argv[0] = expand_exec( argv[0]);
+			if( !argv[0]) {
+				D_( "expand_exec returns NULL.\n");
+				free( t);
+				continue;
+			}
+
+			/* exec_args should be parsed at the moment, too */
+			u = active_db_get_string_var( &EXEC_ARGS, process->pt->name, service);
+			u = fix_variables( u, service);
+			a = split_argv( u, &c);
+			if( c) {
+				if( !a) {
+					D_( "split_argv returns NULL.\n");
+					if( argv[0] != t)
+						free( argv[0]);
+					free( t);
+					free( u);
+					continue;
+				}
+				b = realloc( argv, (argc+c+1)* sizeof*argv);
+				/* if realloc fails, then only argv will used */
+				if( !b) {
+					F_( "realloc returns NULL.\n");
+					free( u);
+					u = NULL;
+				} else {
+					argv = b;
+					memcpy( argv+argc, a, (c+1)*sizeof*argv);
+					argc += c;
+				}
+			}
+
+            if( simple_exec( process, service, argc, argv)) {
+				if( argv[0] != t)
+					free( argv[0]);
+                free( t);
+				if( u)
+					free( u);
+                return TRUE;
             }
             D_("%s did not work\n", t);
-            free(t);
+            free( t);
+			if( u)
+				free( u);
         }
-        return (FAIL);
+        return FAIL;
     }
 
-    return (FALSE);
+    return FALSE;
 }
 
-
-static int simple_exec(process_h * process_to_exec, active_h * s,
-                       char *e, char *ea)
-{
-
+/* 2005-11-28 DEac-: char *e, char *ea => char **argv, size_t argc
+ */
+static int simple_exec(process_h * process_to_exec, active_h * s, size_t argc, char **argv) {
     /* called from inside the service directory, return the PID or 0 on error */
 
     /* This is the real service kicker */
     pid_t pid_fork;             /* pid got from fork() */
-    char **argv = 0;            /* Arguments */
-    int argc;                   /* number of arguments */
 
     assert(process_to_exec);
     assert(s);
     assert(s->name);
-    assert(e);
-
-    if ((pid_fork = initng_fork(s, process_to_exec)) == 0)
-    {
-        char *exec = NULL;
-        char *exec_args = NULL;
-
-        ea = fix_variables(ea, s);
+    assert(argc);
+	assert(argv);
 
-        exec = e;
-        exec_args = ea;
+    if ((pid_fork = initng_fork(s, process_to_exec)) == 0) {
+		int i;
 
-        D_("FROM_FORK simple_exec(%s,%s);\n", e, ea);
-
-        /* get args from service database */
-        if (exec_args)
-        {
-            D_("FROM_FORK (%s): start args: %s\n", exec, exec_args);
-
-            /*
-             * obs!, the split_n, creates a aray, of pointers that points
-             * to exec_args, if exec_args is free, argv is usless!
-             */
-            argv = split_n(exec_args, &argc, 2, 1);
-
-            /* i don't know about this */
-            if (!argv[argc - 1])
-            {
-                argv[argc - 1] = '\0';      /* the last */
-            }
-            else
-            {
-                argv[argc] = '\0';          /* must be null */
-            }
-        }
-        else
-        {
-            argv = initng_calloc(2, sizeof(char *));    /* alloc a null */
-            argv[1] = '\0';                 /* set to null */
-        }
-
-        /* set argv[0] */
-        argv[0] = exec;
-
-
-        {
-            int i;
-
-            for (i = 0; argv[i]; i++)
-                D_("i.e.f.a.e.(): argv[%i]=\"%s\"\n", i, argv[i]);
-        }
+        D_("FROM_FORK simple_exec(%i,%s, ...);\n", argc, argv[0]);
 
+		D_argv( "simple_exec: ", argv);
 
         /* FINALLY EXECUTE *//* execve replaces the running process */
         execve(argv[0], argv, new_environ(s));
 
         /* Will never get here if execve succeeded */
         F_("EEEEEEEEEEEEEEEEEEERRRRRRRRRRRRRRRRRRRRRRRRRRROOOOOOOOOOOOOOOOOOOOOOOOOORRRRRRRRRRRRRRR!!!!!!!!!\n");
-        F_("Cant execute source %s, \"%s\" !\n", e, ea);
-
-        /* free variable, good for making valgrind quit */
-        /*free(argv[0]);
-           free(argv);
-           free(exec_args); */
-
-        /* clean up */
-        /*initng_free(); */
+        F_("Cant execute source %s!\n", argv[0]);
 
-        /* exit 1, to mark a failure */
         _exit(1);
     }
 
@@ -266,7 +305,7 @@
     }
 
     process_to_exec->pid = 0;
-    return (FALSE);
+    return FALSE;
     /* if to test want to lock this up util fork is done ...   waitpid(pid_fork,0,0); */
 }                                           /* end fork_and_exec() */
 


More information about the Initng-svn mailing list