summaryrefslogtreecommitdiffstats
path: root/init
diff options
context:
space:
mode:
authorSan Mehat <san@google.com>2014-09-23 07:48:47 -0700
committerElliott Hughes <enh@google.com>2015-02-02 16:22:56 -0800
commit429721c5c4218679d6ae042d85dd98e3d7ead658 (patch)
tree48a7828344bff171990a586c3ec43729270b1baf /init
parent46adfa69b689bc9f9e15c87275839f233a404582 (diff)
downloadsystem_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.c62
-rw-r--r--init/init.c2
-rw-r--r--init/init.h1
-rw-r--r--init/init_parser.c1
-rw-r--r--init/keywords.h2
-rw-r--r--init/readme.txt10
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