[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