diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2019-06-01 16:35:09 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2019-06-01 16:35:09 +0200 |
commit | 897475ab023040efed9f199af5daffe43451c1d2 (patch) | |
tree | f8f515017525fd7bc08493f5f7fc6696b7d6a857 | |
parent | 6eb6e6a1e9d6e7d4dd154014ce404ec1c8175fb2 (diff) | |
download | busybox-w32-897475ab023040efed9f199af5daffe43451c1d2.tar.gz busybox-w32-897475ab023040efed9f199af5daffe43451c1d2.tar.bz2 busybox-w32-897475ab023040efed9f199af5daffe43451c1d2.zip |
ash: allocate line editing structure only if needed
function old new delta
optschanged 91 128 +37
historycmd 13 17 +4
setcmd 80 78 -2
ash_main 1167 1150 -17
options 576 552 -24
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/3 up/down: 41/-43) Total: -2 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/ash.c | 107 |
1 files changed, 70 insertions, 37 deletions
diff --git a/shell/ash.c b/shell/ash.c index 924e17f32..c8857366c 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -315,9 +315,16 @@ 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: | ||
319 | * ash -c 'set -i; echo $-; sleep 5; echo $-' | ||
320 | * to be ^C-ed and get to interactive ash prompt. | ||
321 | * bash does not support this "set -i". bash also has no | ||
322 | * "set -o interactive". | ||
323 | */ | ||
318 | "i" "interactive", | 324 | "i" "interactive", |
319 | "m" "monitor", | 325 | "m" "monitor", |
320 | "n" "noexec", | 326 | "n" "noexec", |
327 | /* Ditto: bash has no "set -s" and "set -o stdin" */ | ||
321 | "s" "stdin", | 328 | "s" "stdin", |
322 | "x" "xtrace", | 329 | "x" "xtrace", |
323 | "v" "verbose", | 330 | "v" "verbose", |
@@ -334,10 +341,25 @@ static const char *const optletters_optnames[] = { | |||
334 | ,"\0" "debug" | 341 | ,"\0" "debug" |
335 | #endif | 342 | #endif |
336 | }; | 343 | }; |
344 | //bash 4.4.23 also has these opts (with these defaults): | ||
345 | //braceexpand on | ||
346 | //emacs on | ||
347 | //errtrace off | ||
348 | //functrace off | ||
349 | //hashall on | ||
350 | //histexpand off | ||
351 | //history on | ||
352 | //interactive-comments on | ||
353 | //keyword off | ||
354 | //onecmd off | ||
355 | //physical off | ||
356 | //posix off | ||
357 | //privileged off | ||
337 | 358 | ||
338 | #define optletters(n) optletters_optnames[n][0] | 359 | #define optletters(n) optletters_optnames[n][0] |
339 | #define optnames(n) (optletters_optnames[n] + 1) | 360 | #define optnames(n) (optletters_optnames[n] + 1) |
340 | 361 | ||
362 | |||
341 | enum { NOPTS = ARRAY_SIZE(optletters_optnames) }; | 363 | enum { NOPTS = ARRAY_SIZE(optletters_optnames) }; |
342 | 364 | ||
343 | 365 | ||
@@ -9514,8 +9536,8 @@ setinteractive(int on) | |||
9514 | setsignal(SIGINT); | 9536 | setsignal(SIGINT); |
9515 | setsignal(SIGQUIT); | 9537 | setsignal(SIGQUIT); |
9516 | setsignal(SIGTERM); | 9538 | setsignal(SIGTERM); |
9517 | #if !ENABLE_FEATURE_SH_EXTRA_QUIET | ||
9518 | if (is_interactive > 1) { | 9539 | if (is_interactive > 1) { |
9540 | #if !ENABLE_FEATURE_SH_EXTRA_QUIET | ||
9519 | /* Looks like they want an interactive shell */ | 9541 | /* Looks like they want an interactive shell */ |
9520 | static smallint did_banner; | 9542 | static smallint did_banner; |
9521 | 9543 | ||
@@ -9529,8 +9551,12 @@ setinteractive(int on) | |||
9529 | ); | 9551 | ); |
9530 | did_banner = 1; | 9552 | did_banner = 1; |
9531 | } | 9553 | } |
9532 | } | ||
9533 | #endif | 9554 | #endif |
9555 | #if ENABLE_FEATURE_EDITING | ||
9556 | if (!line_input_state) | ||
9557 | line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP); | ||
9558 | #endif | ||
9559 | } | ||
9534 | } | 9560 | } |
9535 | 9561 | ||
9536 | static void | 9562 | static void |
@@ -9542,10 +9568,12 @@ optschanged(void) | |||
9542 | setinteractive(iflag); | 9568 | setinteractive(iflag); |
9543 | setjobctl(mflag); | 9569 | setjobctl(mflag); |
9544 | #if ENABLE_FEATURE_EDITING_VI | 9570 | #if ENABLE_FEATURE_EDITING_VI |
9545 | if (viflag) | 9571 | if (line_input_state) { |
9546 | line_input_state->flags |= VI_MODE; | 9572 | if (viflag) |
9547 | else | 9573 | line_input_state->flags |= VI_MODE; |
9548 | line_input_state->flags &= ~VI_MODE; | 9574 | else |
9575 | line_input_state->flags &= ~VI_MODE; | ||
9576 | } | ||
9549 | #else | 9577 | #else |
9550 | viflag = 0; /* forcibly keep the option off */ | 9578 | viflag = 0; /* forcibly keep the option off */ |
9551 | #endif | 9579 | #endif |
@@ -10519,13 +10547,11 @@ preadfd(void) | |||
10519 | else { | 10547 | else { |
10520 | # if ENABLE_ASH_IDLE_TIMEOUT | 10548 | # if ENABLE_ASH_IDLE_TIMEOUT |
10521 | int timeout = -1; | 10549 | int timeout = -1; |
10522 | if (iflag) { | 10550 | const char *tmout_var = lookupvar("TMOUT"); |
10523 | const char *tmout_var = lookupvar("TMOUT"); | 10551 | if (tmout_var) { |
10524 | if (tmout_var) { | 10552 | timeout = atoi(tmout_var) * 1000; |
10525 | timeout = atoi(tmout_var) * 1000; | 10553 | if (timeout <= 0) |
10526 | if (timeout <= 0) | 10554 | timeout = -1; |
10527 | timeout = -1; | ||
10528 | } | ||
10529 | } | 10555 | } |
10530 | line_input_state->timeout = timeout; | 10556 | line_input_state->timeout = timeout; |
10531 | # endif | 10557 | # endif |
@@ -11086,14 +11112,17 @@ setoption(int flag, int val) | |||
11086 | ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag); | 11112 | ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag); |
11087 | /* NOTREACHED */ | 11113 | /* NOTREACHED */ |
11088 | } | 11114 | } |
11115 | /* If login_sh is not NULL, we are called to parse command line opts, | ||
11116 | * not "set -opts" | ||
11117 | */ | ||
11089 | static int | 11118 | static int |
11090 | options(int cmdline, int *login_sh) | 11119 | options(int *login_sh) |
11091 | { | 11120 | { |
11092 | char *p; | 11121 | char *p; |
11093 | int val; | 11122 | int val; |
11094 | int c; | 11123 | int c; |
11095 | 11124 | ||
11096 | if (cmdline) | 11125 | if (login_sh) |
11097 | minusc = NULL; | 11126 | minusc = NULL; |
11098 | while ((p = *argptr) != NULL) { | 11127 | while ((p = *argptr) != NULL) { |
11099 | c = *p++; | 11128 | c = *p++; |
@@ -11104,7 +11133,7 @@ options(int cmdline, int *login_sh) | |||
11104 | if (c == '-') { | 11133 | if (c == '-') { |
11105 | val = 1; | 11134 | val = 1; |
11106 | if (p[0] == '\0' || LONE_DASH(p)) { | 11135 | if (p[0] == '\0' || LONE_DASH(p)) { |
11107 | if (!cmdline) { | 11136 | if (!login_sh) { |
11108 | /* "-" means turn off -x and -v */ | 11137 | /* "-" means turn off -x and -v */ |
11109 | if (p[0] == '\0') | 11138 | if (p[0] == '\0') |
11110 | xflag = vflag = 0; | 11139 | xflag = vflag = 0; |
@@ -11117,26 +11146,31 @@ options(int cmdline, int *login_sh) | |||
11117 | } | 11146 | } |
11118 | /* first char was + or - */ | 11147 | /* first char was + or - */ |
11119 | while ((c = *p++) != '\0') { | 11148 | while ((c = *p++) != '\0') { |
11120 | /* bash 3.2 indeed handles -c CMD and +c CMD the same */ | 11149 | if (login_sh) { |
11121 | if (c == 'c' && cmdline) { | 11150 | /* bash 3.2 indeed handles -c CMD and +c CMD the same */ |
11122 | minusc = p; /* command is after shell args */ | 11151 | if (c == 'c') { |
11123 | } else if (c == 'o') { | 11152 | minusc = p; /* command is after shell args */ |
11153 | continue; | ||
11154 | } | ||
11155 | if (c == 'l') { | ||
11156 | *login_sh = 1; /* -l or +l == --login */ | ||
11157 | continue; | ||
11158 | } | ||
11159 | /* bash does not accept +-login, we also won't */ | ||
11160 | if (val && (c == '-')) { /* long options */ | ||
11161 | if (strcmp(p, "login") == 0) { | ||
11162 | *login_sh = 1; | ||
11163 | } | ||
11164 | break; | ||
11165 | } | ||
11166 | } | ||
11167 | if (c == 'o') { | ||
11124 | if (plus_minus_o(*argptr, val)) { | 11168 | if (plus_minus_o(*argptr, val)) { |
11125 | /* it already printed err message */ | 11169 | /* it already printed err message */ |
11126 | return 1; /* error */ | 11170 | return 1; /* error */ |
11127 | } | 11171 | } |
11128 | if (*argptr) | 11172 | if (*argptr) |
11129 | argptr++; | 11173 | argptr++; |
11130 | } else if (cmdline && (c == 'l')) { /* -l or +l == --login */ | ||
11131 | if (login_sh) | ||
11132 | *login_sh = 1; | ||
11133 | /* bash does not accept +-login, we also won't */ | ||
11134 | } else if (cmdline && val && (c == '-')) { /* long options */ | ||
11135 | if (strcmp(p, "login") == 0) { | ||
11136 | if (login_sh) | ||
11137 | *login_sh = 1; | ||
11138 | } | ||
11139 | break; | ||
11140 | } else { | 11174 | } else { |
11141 | setoption(c, val); | 11175 | setoption(c, val); |
11142 | } | 11176 | } |
@@ -11227,7 +11261,7 @@ setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
11227 | return showvars(nullstr, 0, VUNSET); | 11261 | return showvars(nullstr, 0, VUNSET); |
11228 | 11262 | ||
11229 | INT_OFF; | 11263 | INT_OFF; |
11230 | retval = options(/*cmdline:*/ 0, NULL); | 11264 | retval = options(/*login_sh:*/ NULL); |
11231 | if (retval == 0) { /* if no parse error... */ | 11265 | if (retval == 0) { /* if no parse error... */ |
11232 | optschanged(); | 11266 | optschanged(); |
11233 | if (*argptr != NULL) { | 11267 | if (*argptr != NULL) { |
@@ -13685,7 +13719,8 @@ helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
13685 | static int FAST_FUNC | 13719 | static int FAST_FUNC |
13686 | historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | 13720 | historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) |
13687 | { | 13721 | { |
13688 | show_history(line_input_state); | 13722 | if (line_input_state) |
13723 | show_history(line_input_state); | ||
13689 | return EXIT_SUCCESS; | 13724 | return EXIT_SUCCESS; |
13690 | } | 13725 | } |
13691 | #endif | 13726 | #endif |
@@ -14001,7 +14036,8 @@ exitshell(void) | |||
14001 | int status; | 14036 | int status; |
14002 | 14037 | ||
14003 | #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT | 14038 | #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT |
14004 | save_history(line_input_state); | 14039 | if (line_input_state) |
14040 | save_history(line_input_state); | ||
14005 | #endif | 14041 | #endif |
14006 | status = exitstatus; | 14042 | status = exitstatus; |
14007 | TRACE(("pid %d, exitshell(%d)\n", getpid(), status)); | 14043 | TRACE(("pid %d, exitshell(%d)\n", getpid(), status)); |
@@ -14123,7 +14159,7 @@ procargs(char **argv) | |||
14123 | argptr = xargv; | 14159 | argptr = xargv; |
14124 | for (i = 0; i < NOPTS; i++) | 14160 | for (i = 0; i < NOPTS; i++) |
14125 | optlist[i] = 2; | 14161 | optlist[i] = 2; |
14126 | if (options(/*cmdline:*/ 1, &login_sh)) { | 14162 | if (options(&login_sh)) { |
14127 | /* it already printed err message */ | 14163 | /* it already printed err message */ |
14128 | raise_exception(EXERROR); | 14164 | raise_exception(EXERROR); |
14129 | } | 14165 | } |
@@ -14249,9 +14285,6 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
14249 | monitor(4, etext, profile_buf, sizeof(profile_buf), 50); | 14285 | monitor(4, etext, profile_buf, sizeof(profile_buf), 50); |
14250 | #endif | 14286 | #endif |
14251 | 14287 | ||
14252 | #if ENABLE_FEATURE_EDITING | ||
14253 | line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP); | ||
14254 | #endif | ||
14255 | state = 0; | 14288 | state = 0; |
14256 | if (setjmp(jmploc.loc)) { | 14289 | if (setjmp(jmploc.loc)) { |
14257 | smallint e; | 14290 | smallint e; |