init: Implement 'exec' command.
(cherry-pick of d05ab3952ec0e38f33a0e80ce6b9eb45b0064ba4.) Change-Id: Id6d9bb32e51a0ad090ed8240cc505dc45b57b35d
This commit is contained in:
parent
46adfa69b6
commit
429721c5c4
|
@ -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]);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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':
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue