aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2019-06-01 16:35:09 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2019-06-01 16:35:09 +0200
commit897475ab023040efed9f199af5daffe43451c1d2 (patch)
treef8f515017525fd7bc08493f5f7fc6696b7d6a857
parent6eb6e6a1e9d6e7d4dd154014ce404ec1c8175fb2 (diff)
downloadbusybox-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.c107
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
341enum { NOPTS = ARRAY_SIZE(optletters_optnames) }; 363enum { 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
9536static void 9562static 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 */
11089static int 11118static int
11090options(int cmdline, int *login_sh) 11119options(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)
13685static int FAST_FUNC 13719static int FAST_FUNC
13686historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) 13720historycmd(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;