diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2011-03-07 12:02:40 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-03-07 12:02:40 +0100 |
commit | aefe1c260ec5aa691e8b6f773c7fa393bfad0f7b (patch) | |
tree | 54df56442e1f060eb0f155b5a860a2562b39ff09 /shell/ash.c | |
parent | 8b6b472f4edd701ac3b25d4a0c89ab506e09e0bb (diff) | |
download | busybox-w32-aefe1c260ec5aa691e8b6f773c7fa393bfad0f7b.tar.gz busybox-w32-aefe1c260ec5aa691e8b6f773c7fa393bfad0f7b.tar.bz2 busybox-w32-aefe1c260ec5aa691e8b6f773c7fa393bfad0f7b.zip |
ash: fix execution of shell scripts without shebang
We were assuming #!/bin/sh, whereas we had to simply re-enter ash.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell/ash.c')
-rw-r--r-- | shell/ash.c | 29 |
1 files changed, 19 insertions, 10 deletions
diff --git a/shell/ash.c b/shell/ash.c index c3c953656..09db046fe 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -7396,8 +7396,6 @@ static int builtinloc = -1; /* index in path of %builtin, or -1 */ | |||
7396 | static void | 7396 | static void |
7397 | tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp) | 7397 | tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp) |
7398 | { | 7398 | { |
7399 | int repeated = 0; | ||
7400 | |||
7401 | #if ENABLE_FEATURE_SH_STANDALONE | 7399 | #if ENABLE_FEATURE_SH_STANDALONE |
7402 | if (applet_no >= 0) { | 7400 | if (applet_no >= 0) { |
7403 | if (APPLET_IS_NOEXEC(applet_no)) { | 7401 | if (APPLET_IS_NOEXEC(applet_no)) { |
@@ -7421,25 +7419,36 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char ** | |||
7421 | #else | 7419 | #else |
7422 | execve(cmd, argv, envp); | 7420 | execve(cmd, argv, envp); |
7423 | #endif | 7421 | #endif |
7424 | if (repeated) { | 7422 | if (cmd == (char*) bb_busybox_exec_path) { |
7423 | /* We already visited ENOEXEC branch below, don't do it again */ | ||
7424 | //TODO: try execve(initial_argv0_of_shell, argv, envp) before giving up? | ||
7425 | free(argv); | 7425 | free(argv); |
7426 | return; | 7426 | return; |
7427 | } | 7427 | } |
7428 | if (errno == ENOEXEC) { | 7428 | if (errno == ENOEXEC) { |
7429 | /* Run "cmd" as a shell script: | ||
7430 | * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html | ||
7431 | * "If the execve() function fails with ENOEXEC, the shell | ||
7432 | * shall execute a command equivalent to having a shell invoked | ||
7433 | * with the command name as its first operand, | ||
7434 | * with any remaining arguments passed to the new shell" | ||
7435 | * | ||
7436 | * That is, do not use $SHELL, user's shell, or /bin/sh; | ||
7437 | * just call ourselves. | ||
7438 | */ | ||
7429 | char **ap; | 7439 | char **ap; |
7430 | char **new; | 7440 | char **new; |
7431 | 7441 | ||
7432 | for (ap = argv; *ap; ap++) | 7442 | for (ap = argv; *ap; ap++) |
7433 | continue; | 7443 | continue; |
7434 | ap = new = ckmalloc((ap - argv + 2) * sizeof(ap[0])); | 7444 | new = ckmalloc((ap - argv + 2) * sizeof(new[0])); |
7435 | ap[1] = cmd; | 7445 | new[0] = (char*) "ash"; |
7436 | ap[0] = cmd = (char *)DEFAULT_SHELL; | 7446 | new[1] = cmd; |
7437 | ap += 2; | 7447 | ap = new + 2; |
7438 | argv++; | 7448 | while ((*ap++ = *++argv) != NULL) |
7439 | while ((*ap++ = *argv++) != NULL) | ||
7440 | continue; | 7449 | continue; |
7450 | cmd = (char*) bb_busybox_exec_path; | ||
7441 | argv = new; | 7451 | argv = new; |
7442 | repeated++; | ||
7443 | goto repeat; | 7452 | goto repeat; |
7444 | } | 7453 | } |
7445 | } | 7454 | } |