diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2016-10-26 22:29:11 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2016-10-26 22:29:11 +0200 |
commit | 65a8b859a9a3f2bb4a62c15ca1f4d01288593734 (patch) | |
tree | 11965425b70a8cb6f40a7ad1d4d64e730be313bb | |
parent | 0e081d01a8ae37df11af612eb65d858c1c0f28be (diff) | |
download | busybox-w32-65a8b859a9a3f2bb4a62c15ca1f4d01288593734.tar.gz busybox-w32-65a8b859a9a3f2bb4a62c15ca1f4d01288593734.tar.bz2 busybox-w32-65a8b859a9a3f2bb4a62c15ca1f4d01288593734.zip |
ash: optimize tryexec(): avoid one allocation
There was a bug in tryexec which bbox had fixed in 2003.
dash had a smaller fix in 2007. Copy it. It is smaller,
although it is also more quirky (requires argv[-1] to exist).
Upstream commit 1:
Date: Mon, 15 Oct 2007 20:24:28 +0800
[EXEC] Fixed execing of scripts with no hash-bang
The function tryexec used the original name instead of the path found through
PATH search. This patch fixes that.
Test case:
trap 'rm -f $TMP' EXIT
TMP=$(tempfile -s nosuchthing)
cat <<- EOF > $TMP
echo OK
EOF
chmod u+x $TMP
cd /
PATH=${TMP%/*} ${TMP##*/}
Old result:
/bin/sh: Can't open filelgY4Fanosuchthing
New result:
OK
Upstream commit 2:
Date: Sun, 23 Dec 2007 11:02:26 +0800
[EVAL] Fix bad pointer arithmetic in evalcommand
dash dies on sparc with a SIGBUS due to an arithmetic error introduced
with commit 03b4958, this patch fixes it.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
function old new delta
evalcommand 1261 1264 +3
dotcmd 321 319 -2
tryexec 115 64 -51
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/2 up/down: 3/-53) Total: -50 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/ash.c | 31 |
1 files changed, 11 insertions, 20 deletions
diff --git a/shell/ash.c b/shell/ash.c index 8bf02e6a7..133b2d40e 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -7467,13 +7467,7 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char ** | |||
7467 | #else | 7467 | #else |
7468 | execve(cmd, argv, envp); | 7468 | execve(cmd, argv, envp); |
7469 | #endif | 7469 | #endif |
7470 | if (cmd == (char*) bb_busybox_exec_path) { | 7470 | if (cmd != (char*) bb_busybox_exec_path && errno == ENOEXEC) { |
7471 | /* We already visited ENOEXEC branch below, don't do it again */ | ||
7472 | //TODO: try execve(initial_argv0_of_shell, argv, envp) before giving up? | ||
7473 | free(argv); | ||
7474 | return; | ||
7475 | } | ||
7476 | if (errno == ENOEXEC) { | ||
7477 | /* Run "cmd" as a shell script: | 7471 | /* Run "cmd" as a shell script: |
7478 | * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html | 7472 | * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html |
7479 | * "If the execve() function fails with ENOEXEC, the shell | 7473 | * "If the execve() function fails with ENOEXEC, the shell |
@@ -7490,19 +7484,13 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char ** | |||
7490 | * message and exit code 126. For one, this prevents attempts | 7484 | * message and exit code 126. For one, this prevents attempts |
7491 | * to interpret foreign ELF binaries as shell scripts. | 7485 | * to interpret foreign ELF binaries as shell scripts. |
7492 | */ | 7486 | */ |
7493 | char **ap; | 7487 | argv[0] = cmd; |
7494 | char **new; | ||
7495 | |||
7496 | for (ap = argv; *ap; ap++) | ||
7497 | continue; | ||
7498 | new = ckmalloc((ap - argv + 2) * sizeof(new[0])); | ||
7499 | new[0] = (char*) "ash"; | ||
7500 | new[1] = cmd; | ||
7501 | ap = new + 2; | ||
7502 | while ((*ap++ = *++argv) != NULL) | ||
7503 | continue; | ||
7504 | cmd = (char*) bb_busybox_exec_path; | 7488 | cmd = (char*) bb_busybox_exec_path; |
7505 | argv = new; | 7489 | /* NB: this is only possible because all callers of shellexec() |
7490 | * ensure that the argv[-1] slot exists! | ||
7491 | */ | ||
7492 | argv--; | ||
7493 | argv[0] = (char*) "ash"; | ||
7506 | goto repeat; | 7494 | goto repeat; |
7507 | } | 7495 | } |
7508 | } | 7496 | } |
@@ -7510,6 +7498,7 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char ** | |||
7510 | /* | 7498 | /* |
7511 | * Exec a program. Never returns. If you change this routine, you may | 7499 | * Exec a program. Never returns. If you change this routine, you may |
7512 | * have to change the find_command routine as well. | 7500 | * have to change the find_command routine as well. |
7501 | * argv[-1] must exist and be writable! See tryexec() for why. | ||
7513 | */ | 7502 | */ |
7514 | static void shellexec(char **, const char *, int) NORETURN; | 7503 | static void shellexec(char **, const char *, int) NORETURN; |
7515 | static void | 7504 | static void |
@@ -9415,7 +9404,9 @@ evalcommand(union node *cmd, int flags) | |||
9415 | argc++; | 9404 | argc++; |
9416 | } | 9405 | } |
9417 | 9406 | ||
9418 | argv = nargv = stalloc(sizeof(char *) * (argc + 1)); | 9407 | /* Reserve one extra spot at the front for shellexec. */ |
9408 | nargv = stalloc(sizeof(char *) * (argc + 2)); | ||
9409 | argv = ++nargv; | ||
9419 | for (sp = arglist.list; sp; sp = sp->next) { | 9410 | for (sp = arglist.list; sp; sp = sp->next) { |
9420 | TRACE(("evalcommand arg: %s\n", sp->text)); | 9411 | TRACE(("evalcommand arg: %s\n", sp->text)); |
9421 | *nargv++ = sp->text; | 9412 | *nargv++ = sp->text; |