diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2019-06-03 12:21:04 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2019-06-03 12:21:04 +0200 |
commit | f3634584d0fdeb4ae9e2fe0f5971d45b77e40296 (patch) | |
tree | 28a97129b30b28106b4f9fae7ddfbc5be12ba0f6 | |
parent | 897475ab023040efed9f199af5daffe43451c1d2 (diff) | |
download | busybox-w32-f3634584d0fdeb4ae9e2fe0f5971d45b77e40296.tar.gz busybox-w32-f3634584d0fdeb4ae9e2fe0f5971d45b77e40296.tar.bz2 busybox-w32-f3634584d0fdeb4ae9e2fe0f5971d45b77e40296.zip |
ash,hush: show 'c' in $- if run in "sh -c CMD"
function old new delta
options 552 599 +47
expand_one_var 2375 2385 +10
optletters_optnames 60 64 +4
hush_main 1108 1111 +3
ash_main 1150 1152 +2
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 5/0 up/down: 66/0) Total: 66 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/ash.c | 62 | ||||
-rw-r--r-- | shell/hush.c | 13 |
2 files changed, 50 insertions, 25 deletions
diff --git a/shell/ash.c b/shell/ash.c index c8857366c..e3bbac9a0 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -315,17 +315,18 @@ static const char *const optletters_optnames[] = { | |||
315 | "e" "errexit", | 315 | "e" "errexit", |
316 | "f" "noglob", | 316 | "f" "noglob", |
317 | "I" "ignoreeof", | 317 | "I" "ignoreeof", |
318 | /* The below allows this invocation: | 318 | /* The below allowed this invocation: |
319 | * ash -c 'set -i; echo $-; sleep 5; echo $-' | 319 | * ash -c 'set -i; echo $-; sleep 5; echo $-' |
320 | * to be ^C-ed and get to interactive ash prompt. | 320 | * to be ^C-ed and get to interactive ash prompt. |
321 | * bash does not support this "set -i". bash also has no | 321 | * bash does not support such "set -i". |
322 | * "set -o interactive". | 322 | * In our code, this is denoted by empty long name: |
323 | */ | 323 | */ |
324 | "i" "interactive", | 324 | "i" "", |
325 | "m" "monitor", | 325 | "m" "monitor", |
326 | "n" "noexec", | 326 | "n" "noexec", |
327 | /* Ditto: bash has no "set -s" and "set -o stdin" */ | 327 | /* Ditto: bash has no "set -s" */ |
328 | "s" "stdin", | 328 | "s" "", |
329 | "c" "", | ||
329 | "x" "xtrace", | 330 | "x" "xtrace", |
330 | "v" "verbose", | 331 | "v" "verbose", |
331 | "C" "noclobber", | 332 | "C" "noclobber", |
@@ -359,7 +360,6 @@ static const char *const optletters_optnames[] = { | |||
359 | #define optletters(n) optletters_optnames[n][0] | 360 | #define optletters(n) optletters_optnames[n][0] |
360 | #define optnames(n) (optletters_optnames[n] + 1) | 361 | #define optnames(n) (optletters_optnames[n] + 1) |
361 | 362 | ||
362 | |||
363 | enum { NOPTS = ARRAY_SIZE(optletters_optnames) }; | 363 | enum { NOPTS = ARRAY_SIZE(optletters_optnames) }; |
364 | 364 | ||
365 | 365 | ||
@@ -419,21 +419,22 @@ struct globals_misc { | |||
419 | #define mflag optlist[4] | 419 | #define mflag optlist[4] |
420 | #define nflag optlist[5] | 420 | #define nflag optlist[5] |
421 | #define sflag optlist[6] | 421 | #define sflag optlist[6] |
422 | #define xflag optlist[7] | 422 | #define cflag optlist[7] |
423 | #define vflag optlist[8] | 423 | #define xflag optlist[8] |
424 | #define Cflag optlist[9] | 424 | #define vflag optlist[9] |
425 | #define aflag optlist[10] | 425 | #define Cflag optlist[10] |
426 | #define bflag optlist[11] | 426 | #define aflag optlist[11] |
427 | #define uflag optlist[12] | 427 | #define bflag optlist[12] |
428 | #define viflag optlist[13] | 428 | #define uflag optlist[13] |
429 | #define viflag optlist[14] | ||
429 | #if BASH_PIPEFAIL | 430 | #if BASH_PIPEFAIL |
430 | # define pipefail optlist[14] | 431 | # define pipefail optlist[15] |
431 | #else | 432 | #else |
432 | # define pipefail 0 | 433 | # define pipefail 0 |
433 | #endif | 434 | #endif |
434 | #if DEBUG | 435 | #if DEBUG |
435 | # define nolog optlist[14 + BASH_PIPEFAIL] | 436 | # define nolog optlist[15 + BASH_PIPEFAIL] |
436 | # define debug optlist[15 + BASH_PIPEFAIL] | 437 | # define debug optlist[16 + BASH_PIPEFAIL] |
437 | #endif | 438 | #endif |
438 | 439 | ||
439 | /* trap handler commands */ | 440 | /* trap handler commands */ |
@@ -11104,7 +11105,7 @@ setoption(int flag, int val) | |||
11104 | int i; | 11105 | int i; |
11105 | 11106 | ||
11106 | for (i = 0; i < NOPTS; i++) { | 11107 | for (i = 0; i < NOPTS; i++) { |
11107 | if (optletters(i) == flag) { | 11108 | if (optletters(i) == flag && optnames(i)[0] != '\0') { |
11108 | optlist[i] = val; | 11109 | optlist[i] = val; |
11109 | return; | 11110 | return; |
11110 | } | 11111 | } |
@@ -11150,6 +11151,15 @@ options(int *login_sh) | |||
11150 | /* bash 3.2 indeed handles -c CMD and +c CMD the same */ | 11151 | /* bash 3.2 indeed handles -c CMD and +c CMD the same */ |
11151 | if (c == 'c') { | 11152 | if (c == 'c') { |
11152 | minusc = p; /* command is after shell args */ | 11153 | minusc = p; /* command is after shell args */ |
11154 | cflag = 1; | ||
11155 | continue; | ||
11156 | } | ||
11157 | if (c == 's') { /* -s, +s */ | ||
11158 | sflag = 1; | ||
11159 | continue; | ||
11160 | } | ||
11161 | if (c == 'i') { /* -i, +i */ | ||
11162 | iflag = 1; | ||
11153 | continue; | 11163 | continue; |
11154 | } | 11164 | } |
11155 | if (c == 'l') { | 11165 | if (c == 'l') { |
@@ -14170,8 +14180,13 @@ procargs(char **argv) | |||
14170 | ash_msg_and_raise_error(bb_msg_requires_arg, "-c"); | 14180 | ash_msg_and_raise_error(bb_msg_requires_arg, "-c"); |
14171 | sflag = 1; | 14181 | sflag = 1; |
14172 | } | 14182 | } |
14173 | if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1)) | 14183 | if (iflag == 2 /* no explicit -i given */ |
14184 | && sflag == 1 /* -s given (or implied) */ | ||
14185 | && !minusc /* bash compat: ash -sc 'echo $-' is not interactive (dash is) */ | ||
14186 | && isatty(0) && isatty(1) /* we are on tty */ | ||
14187 | ) { | ||
14174 | iflag = 1; | 14188 | iflag = 1; |
14189 | } | ||
14175 | if (mflag == 2) | 14190 | if (mflag == 2) |
14176 | mflag = iflag; | 14191 | mflag = iflag; |
14177 | for (i = 0; i < NOPTS; i++) | 14192 | for (i = 0; i < NOPTS; i++) |
@@ -14359,10 +14374,17 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
14359 | * Ensure we don't falsely claim that 0 (stdin) | 14374 | * Ensure we don't falsely claim that 0 (stdin) |
14360 | * is one of stacked source fds. | 14375 | * is one of stacked source fds. |
14361 | * Testcase: ash -c 'exec 1>&0' must not complain. */ | 14376 | * Testcase: ash -c 'exec 1>&0' must not complain. */ |
14377 | |||
14362 | // if (!sflag) g_parsefile->pf_fd = -1; | 14378 | // if (!sflag) g_parsefile->pf_fd = -1; |
14363 | // ^^ not necessary since now we special-case fd 0 | 14379 | // ^^ not necessary since now we special-case fd 0 |
14364 | // in save_fd_on_redirect() | 14380 | // in save_fd_on_redirect() |
14365 | evalstring(minusc, sflag ? 0 : EV_EXIT); | 14381 | |
14382 | // dash: evalstring(minusc, sflag ? 0 : EV_EXIT); | ||
14383 | // The above makes | ||
14384 | // ash -sc 'echo $-' | ||
14385 | // continue reading input from stdin after running 'echo'. | ||
14386 | // bash does not do this: it prints "hBcs" and exits. | ||
14387 | evalstring(minusc, EV_EXIT); | ||
14366 | } | 14388 | } |
14367 | 14389 | ||
14368 | if (sflag || minusc == NULL) { | 14390 | if (sflag || minusc == NULL) { |
diff --git a/shell/hush.c b/shell/hush.c index 4b08232a4..f82747f74 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -903,6 +903,7 @@ struct globals { | |||
903 | # define G_x_mode 0 | 903 | # define G_x_mode 0 |
904 | #endif | 904 | #endif |
905 | char opt_s; | 905 | char opt_s; |
906 | char opt_c; | ||
906 | #if ENABLE_HUSH_INTERACTIVE | 907 | #if ENABLE_HUSH_INTERACTIVE |
907 | smallint promptmode; /* 0: PS1, 1: PS2 */ | 908 | smallint promptmode; /* 0: PS1, 1: PS2 */ |
908 | #endif | 909 | #endif |
@@ -1009,7 +1010,7 @@ struct globals { | |||
1009 | int debug_indent; | 1010 | int debug_indent; |
1010 | #endif | 1011 | #endif |
1011 | struct sigaction sa; | 1012 | struct sigaction sa; |
1012 | char optstring_buf[sizeof("eixs")]; | 1013 | char optstring_buf[sizeof("eixcs")]; |
1013 | #if BASH_EPOCH_VARS | 1014 | #if BASH_EPOCH_VARS |
1014 | char epoch_buf[sizeof("%lu.nnnnnn") + sizeof(long)*3]; | 1015 | char epoch_buf[sizeof("%lu.nnnnnn") + sizeof(long)*3]; |
1015 | #endif | 1016 | #endif |
@@ -6414,9 +6415,10 @@ static NOINLINE int expand_one_var(o_string *output, int n, | |||
6414 | * commands read but are not executed, | 6415 | * commands read but are not executed, |
6415 | * so $- can not execute too, 'n' is never seen in $-. | 6416 | * so $- can not execute too, 'n' is never seen in $-. |
6416 | */ | 6417 | */ |
6418 | if (G.opt_c) | ||
6419 | *cp++ = 'c'; | ||
6417 | if (G.opt_s) | 6420 | if (G.opt_s) |
6418 | *cp++ = 's'; | 6421 | *cp++ = 's'; |
6419 | //TODO: show 'c' if executed via "hush -c 'CMDS'" (bash only, not ash) | ||
6420 | *cp = '\0'; | 6422 | *cp = '\0'; |
6421 | break; | 6423 | break; |
6422 | } | 6424 | } |
@@ -9859,7 +9861,6 @@ int hush_main(int argc, char **argv) | |||
9859 | { | 9861 | { |
9860 | enum { | 9862 | enum { |
9861 | OPT_login = (1 << 0), | 9863 | OPT_login = (1 << 0), |
9862 | OPT_s = (1 << 1), | ||
9863 | }; | 9864 | }; |
9864 | unsigned flags; | 9865 | unsigned flags; |
9865 | unsigned builtin_argc; | 9866 | unsigned builtin_argc; |
@@ -10029,6 +10030,7 @@ int hush_main(int argc, char **argv) | |||
10029 | } | 10030 | } |
10030 | goto final_return; | 10031 | goto final_return; |
10031 | } | 10032 | } |
10033 | G.opt_c = 1; | ||
10032 | if (!G.global_argv[0]) { | 10034 | if (!G.global_argv[0]) { |
10033 | /* -c 'script' (no params): prevent empty $0 */ | 10035 | /* -c 'script' (no params): prevent empty $0 */ |
10034 | G.global_argv--; /* points to argv[i] of 'script' */ | 10036 | G.global_argv--; /* points to argv[i] of 'script' */ |
@@ -10044,7 +10046,7 @@ int hush_main(int argc, char **argv) | |||
10044 | /* G_interactive_fd++; */ | 10046 | /* G_interactive_fd++; */ |
10045 | break; | 10047 | break; |
10046 | case 's': | 10048 | case 's': |
10047 | flags |= OPT_s; | 10049 | G.opt_s = 1; |
10048 | break; | 10050 | break; |
10049 | case 'l': | 10051 | case 'l': |
10050 | flags |= OPT_login; | 10052 | flags |= OPT_login; |
@@ -10154,7 +10156,7 @@ int hush_main(int argc, char **argv) | |||
10154 | } | 10156 | } |
10155 | 10157 | ||
10156 | /* -s is: hush -s ARGV1 ARGV2 (no SCRIPT) */ | 10158 | /* -s is: hush -s ARGV1 ARGV2 (no SCRIPT) */ |
10157 | if (!(flags & OPT_s) && G.global_argv[1]) { | 10159 | if (!G.opt_s && G.global_argv[1]) { |
10158 | HFILE *input; | 10160 | HFILE *input; |
10159 | /* | 10161 | /* |
10160 | * "bash <script>" (which is never interactive (unless -i?)) | 10162 | * "bash <script>" (which is never interactive (unless -i?)) |
@@ -10178,6 +10180,7 @@ int hush_main(int argc, char **argv) | |||
10178 | #endif | 10180 | #endif |
10179 | goto final_return; | 10181 | goto final_return; |
10180 | } | 10182 | } |
10183 | /* "implicit" -s: bare interactive hush shows 's' in $- */ | ||
10181 | G.opt_s = 1; | 10184 | G.opt_s = 1; |
10182 | 10185 | ||
10183 | /* Up to here, shell was non-interactive. Now it may become one. | 10186 | /* Up to here, shell was non-interactive. Now it may become one. |