diff options
author | Willy Tarreau <w@1wt.eu> | 2007-12-16 08:53:39 +0100 |
---|---|---|
committer | Willy Tarreau <w@1wt.eu> | 2007-12-16 08:53:39 +0100 |
commit | a62b8562472584c2d6611ea1c3c3355bed580bc2 (patch) | |
tree | 8737c3205133fc11fe4382574a6c54269a0ad0a8 | |
parent | build: remove extraneous '-Os' in diet call (diff) | |
download | flxutils-a62b8562472584c2d6611ea1c3c3355bed580bc2.tar.xz |
init: add the "br" command to branch without returning
Many scripts are written with a terminating "in /bin/sh", but this
causes some trouble because /bin/sh is passed init's args which are
invalid for sh.
A new "br" command (for "branch") works exactly like "ex" except
that it does not return in case of success. It simply does a pure
execve(). It also supports arguments if necessary.
So as of now, it is recommended that preinit scripts finish with
"br /bin/sh".
-rw-r--r-- | init/init.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/init/init.c b/init/init.c index a9874ac..a1949b0 100644 --- a/init/init.c +++ b/init/init.c @@ -299,6 +299,7 @@ enum { TOK_MT, /* mt : mount */ TOK_RE, /* re : remount */ TOK_IN, /* in : set init program */ + TOK_BR, /* br : branch (=execute without forking) */ TOK_EX, /* ex : execute */ TOK_RX, /* rx : execute under chroot */ TOK_BL, /* bl : make block devices */ @@ -328,7 +329,7 @@ enum { }; /* counts from TOK_LN to TOK_DOT */ -#define NB_TOKENS 25 +#define NB_TOKENS 26 /* possible states for variable parsing */ enum { @@ -352,6 +353,7 @@ static const __attribute__ ((__section__(STR_SECT),__aligned__(1))) struct { "mt", 'M', 3, /* TOK_MT */ "re", 0, 3, /* TOK_RE */ "in", 'I', 1, /* TOK_IN */ + "br", 0, 1, /* TOK_BR */ "ex", 'E', 1, /* TOK_EX */ "rx", 'R', 2, /* TOK_RX */ "bl", 'B', 6, /* TOK_BL */ @@ -399,7 +401,7 @@ static const __attribute__ ((__section__(STR_SECT),__aligned__(1))) struct { { "tty", GID_TTY, 5, 0, 0666 | S_IFCHR }, { "ptmx", GID_TTY, 5, 2, 0666 | S_IFCHR }, { "initctl", GID_ROOT, 0, 0, 0600 | S_IFIFO }, -} ; +}; static char cfg_data[MAX_CFG_SIZE]; static char *cfg_args[MAX_CFG_ARGS]; @@ -1701,14 +1703,17 @@ int main(int argc, char **argv, char **envp) { break; } + case TOK_BR: + /* br cmd [cfg_args] : execute cmd with cfg_args but do not return */ + /* fall through TOK_EX/TOK_RX and never fork nor exit */ case TOK_EX: - /* E cmd [cfg_args] : execute cmd with cfg_args, chrooted to dir */ + /* E cmd [cfg_args] : execute cmd with cfg_args */ /* fall through TOK_RX */ case TOK_RX: { /* R dir cmd [cfg_args] : execute cmd with cfg_args, chrooted to dir */ int res; - res = fork(); + res = (token == TOK_BR) ? 0 : fork(); if (res == 0) { char **exec_args; /* OK, here's the problem : @@ -1732,12 +1737,13 @@ int main(int argc, char **argv, char **envp) { exec_args++; } - res = fork(); + res = (token == TOK_BR) ? 0 : fork(); if (res == 0) { execve(exec_args[0], exec_args, envp); print("<E>xec(child) : execve() failed\n"); //printf("after execve(%s)!\n", exec_args[0]); - exit(1); + if (token != TOK_BR) + exit(1); } else if (res > 0) { int ret, rem; @@ -1758,7 +1764,8 @@ int main(int argc, char **argv, char **envp) { exit(((ret == -1) || !WIFEXITED(status)) ? 1 : WEXITSTATUS(status)); } - exit(1); + if (token != TOK_BR) + exit(1); } else if (res > 0) { int ret; |