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; |
