diff options
author | San Mehat <san@google.com> | 2014-09-23 07:48:47 -0700 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2015-02-02 16:22:56 -0800 |
commit | 429721c5c4218679d6ae042d85dd98e3d7ead658 (patch) | |
tree | 48a7828344bff171990a586c3ec43729270b1baf /init | |
parent | 46adfa69b689bc9f9e15c87275839f233a404582 (diff) | |
download | system_core-429721c5c4218679d6ae042d85dd98e3d7ead658.zip system_core-429721c5c4218679d6ae042d85dd98e3d7ead658.tar.gz system_core-429721c5c4218679d6ae042d85dd98e3d7ead658.tar.bz2 |
init: Implement 'exec' command.
(cherry-pick of d05ab3952ec0e38f33a0e80ce6b9eb45b0064ba4.)
Change-Id: Id6d9bb32e51a0ad090ed8240cc505dc45b57b35d
Diffstat (limited to 'init')
-rw-r--r-- | init/builtins.c | 62 | ||||
-rw-r--r-- | init/init.c | 2 | ||||
-rw-r--r-- | init/init.h | 1 | ||||
-rw-r--r-- | init/init_parser.c | 1 | ||||
-rw-r--r-- | init/keywords.h | 2 | ||||
-rw-r--r-- | init/readme.txt | 10 |
6 files changed, 74 insertions, 4 deletions
diff --git a/init/builtins.c b/init/builtins.c index b9b5029..303a8ca 100644 --- a/init/builtins.c +++ b/init/builtins.c @@ -205,6 +205,68 @@ int do_exec(int nargs, char **args) return -1; } +int do_execonce(int nargs, char **args) +{ + pid_t child; + int child_status = 0; + static int already_done; + + if (already_done) { + return -1; + } + already_done = 1; + if (!(child = fork())) { + /* + * Child process. + */ + zap_stdio(); + char *exec_args[100]; + int i; + int num_process_args = nargs; + + memset(exec_args, 0, sizeof(exec_args)); + if (num_process_args > ARRAY_SIZE(exec_args) - 1) { + ERROR("exec called with %d args, limit is %d", num_process_args, + ARRAY_SIZE(exec_args) - 1); + _exit(1); + } + for (i = 1; i < num_process_args; i++) + exec_args[i - 1] = args[i]; + + if (execv(exec_args[0], exec_args) == -1) { + ERROR("Failed to execv '%s' (%s)", exec_args[0], strerror(errno)); + _exit(1); + } + ERROR("Returned from execv()!"); + _exit(1); + } + + /* + * Parent process. + */ + if (child == -1) { + ERROR("Fork failed\n"); + return -1; + } + + if (TEMP_FAILURE_RETRY(waitpid(child, &child_status, 0)) == -1) { + ERROR("waitpid(): failed (%s)\n", strerror(errno)); + return -1; + } + + if (WIFSIGNALED(child_status)) { + INFO("Child exited due to signal %d\n", WTERMSIG(child_status)); + return -1; + } else if (WIFEXITED(child_status)) { + INFO("Child exited normally (exit code %d)\n", WEXITSTATUS(child_status)); + return WEXITSTATUS(child_status); + } + + ERROR("Abnormal child process exit\n"); + + return -1; +} + int do_export(int nargs, char **args) { return add_environment(args[1], args[2]); diff --git a/init/init.c b/init/init.c index d3dd019..096d898 100644 --- a/init/init.c +++ b/init/init.c @@ -126,7 +126,7 @@ int add_environment(const char *key, const char *val) return -1; } -static void zap_stdio(void) +void zap_stdio(void) { int fd; fd = open("/dev/null", O_RDWR); diff --git a/init/init.h b/init/init.h index e03bd53..654a80b 100644 --- a/init/init.h +++ b/init/init.h @@ -149,5 +149,6 @@ void property_changed(const char *name, const char *value); extern struct selabel_handle *sehandle; extern struct selabel_handle *sehandle_prop; extern int selinux_reload_policy(void); +void zap_stdio(void); #endif /* _INIT_INIT_H */ diff --git a/init/init_parser.c b/init/init_parser.c index a124fa2..02cbf3d 100644 --- a/init/init_parser.c +++ b/init/init_parser.c @@ -97,6 +97,7 @@ static int lookup_keyword(const char *s) case 'e': if (!strcmp(s, "nable")) return K_enable; if (!strcmp(s, "xec")) return K_exec; + if (!strcmp(s, "xeconce")) return K_execonce; if (!strcmp(s, "xport")) return K_export; break; case 'g': diff --git a/init/keywords.h b/init/keywords.h index 2d97e5b..7473586 100644 --- a/init/keywords.h +++ b/init/keywords.h @@ -8,6 +8,7 @@ int do_class_reset(int nargs, char **args); int do_domainname(int nargs, char **args); int do_enable(int nargs, char **args); int do_exec(int nargs, char **args); +int do_execonce(int nargs, char **args); int do_export(int nargs, char **args); int do_hostname(int nargs, char **args); int do_ifup(int nargs, char **args); @@ -59,6 +60,7 @@ enum { KEYWORD(domainname, COMMAND, 1, do_domainname) KEYWORD(enable, COMMAND, 1, do_enable) KEYWORD(exec, COMMAND, 1, do_exec) + KEYWORD(execonce, COMMAND, 1, do_execonce) KEYWORD(export, COMMAND, 2, do_export) KEYWORD(group, OPTION, 0, 0) KEYWORD(hostname, COMMAND, 1, do_hostname) diff --git a/init/readme.txt b/init/readme.txt index 0b43fd5..132a869 100644 --- a/init/readme.txt +++ b/init/readme.txt @@ -136,10 +136,14 @@ Commands -------- exec <path> [ <argument> ]* + This command is not implemented. + +execonce <path> [ <argument> ]* Fork and execute a program (<path>). This will block until - the program completes execution. It is best to avoid exec - as unlike the builtin commands, it runs the risk of getting - init "stuck". (??? maybe there should be a timeout?) + the program completes execution. This command can be run at most + once during init's lifetime. Subsequent invocations are ignored. + It is best to avoid exec as unlike the builtin commands, it runs + the risk of getting init "stuck". export <name> <value> Set the environment variable <name> equal to <value> in the |