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>
This commit is contained in:
Denys Vlasenko 2019-06-01 16:35:09 +02:00
parent 6eb6e6a1e9
commit 897475ab02

View File

@ -315,9 +315,16 @@ static const char *const optletters_optnames[] = {
"e" "errexit", "e" "errexit",
"f" "noglob", "f" "noglob",
"I" "ignoreeof", "I" "ignoreeof",
/* The below allows this invocation:
* ash -c 'set -i; echo $-; sleep 5; echo $-'
* to be ^C-ed and get to interactive ash prompt.
* bash does not support this "set -i". bash also has no
* "set -o interactive".
*/
"i" "interactive", "i" "interactive",
"m" "monitor", "m" "monitor",
"n" "noexec", "n" "noexec",
/* Ditto: bash has no "set -s" and "set -o stdin" */
"s" "stdin", "s" "stdin",
"x" "xtrace", "x" "xtrace",
"v" "verbose", "v" "verbose",
@ -334,10 +341,25 @@ static const char *const optletters_optnames[] = {
,"\0" "debug" ,"\0" "debug"
#endif #endif
}; };
//bash 4.4.23 also has these opts (with these defaults):
//braceexpand on
//emacs on
//errtrace off
//functrace off
//hashall on
//histexpand off
//history on
//interactive-comments on
//keyword off
//onecmd off
//physical off
//posix off
//privileged off
#define optletters(n) optletters_optnames[n][0] #define optletters(n) optletters_optnames[n][0]
#define optnames(n) (optletters_optnames[n] + 1) #define optnames(n) (optletters_optnames[n] + 1)
enum { NOPTS = ARRAY_SIZE(optletters_optnames) }; enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
@ -9514,8 +9536,8 @@ setinteractive(int on)
setsignal(SIGINT); setsignal(SIGINT);
setsignal(SIGQUIT); setsignal(SIGQUIT);
setsignal(SIGTERM); setsignal(SIGTERM);
#if !ENABLE_FEATURE_SH_EXTRA_QUIET
if (is_interactive > 1) { if (is_interactive > 1) {
#if !ENABLE_FEATURE_SH_EXTRA_QUIET
/* Looks like they want an interactive shell */ /* Looks like they want an interactive shell */
static smallint did_banner; static smallint did_banner;
@ -9529,8 +9551,12 @@ setinteractive(int on)
); );
did_banner = 1; did_banner = 1;
} }
}
#endif #endif
#if ENABLE_FEATURE_EDITING
if (!line_input_state)
line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
#endif
}
} }
static void static void
@ -9542,10 +9568,12 @@ optschanged(void)
setinteractive(iflag); setinteractive(iflag);
setjobctl(mflag); setjobctl(mflag);
#if ENABLE_FEATURE_EDITING_VI #if ENABLE_FEATURE_EDITING_VI
if (viflag) if (line_input_state) {
line_input_state->flags |= VI_MODE; if (viflag)
else line_input_state->flags |= VI_MODE;
line_input_state->flags &= ~VI_MODE; else
line_input_state->flags &= ~VI_MODE;
}
#else #else
viflag = 0; /* forcibly keep the option off */ viflag = 0; /* forcibly keep the option off */
#endif #endif
@ -10519,13 +10547,11 @@ preadfd(void)
else { else {
# if ENABLE_ASH_IDLE_TIMEOUT # if ENABLE_ASH_IDLE_TIMEOUT
int timeout = -1; int timeout = -1;
if (iflag) { const char *tmout_var = lookupvar("TMOUT");
const char *tmout_var = lookupvar("TMOUT"); if (tmout_var) {
if (tmout_var) { timeout = atoi(tmout_var) * 1000;
timeout = atoi(tmout_var) * 1000; if (timeout <= 0)
if (timeout <= 0) timeout = -1;
timeout = -1;
}
} }
line_input_state->timeout = timeout; line_input_state->timeout = timeout;
# endif # endif
@ -11086,14 +11112,17 @@ setoption(int flag, int val)
ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag); ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
/* NOTREACHED */ /* NOTREACHED */
} }
/* If login_sh is not NULL, we are called to parse command line opts,
* not "set -opts"
*/
static int static int
options(int cmdline, int *login_sh) options(int *login_sh)
{ {
char *p; char *p;
int val; int val;
int c; int c;
if (cmdline) if (login_sh)
minusc = NULL; minusc = NULL;
while ((p = *argptr) != NULL) { while ((p = *argptr) != NULL) {
c = *p++; c = *p++;
@ -11104,7 +11133,7 @@ options(int cmdline, int *login_sh)
if (c == '-') { if (c == '-') {
val = 1; val = 1;
if (p[0] == '\0' || LONE_DASH(p)) { if (p[0] == '\0' || LONE_DASH(p)) {
if (!cmdline) { if (!login_sh) {
/* "-" means turn off -x and -v */ /* "-" means turn off -x and -v */
if (p[0] == '\0') if (p[0] == '\0')
xflag = vflag = 0; xflag = vflag = 0;
@ -11117,26 +11146,31 @@ options(int cmdline, int *login_sh)
} }
/* first char was + or - */ /* first char was + or - */
while ((c = *p++) != '\0') { while ((c = *p++) != '\0') {
/* bash 3.2 indeed handles -c CMD and +c CMD the same */ if (login_sh) {
if (c == 'c' && cmdline) { /* bash 3.2 indeed handles -c CMD and +c CMD the same */
minusc = p; /* command is after shell args */ if (c == 'c') {
} else if (c == 'o') { minusc = p; /* command is after shell args */
continue;
}
if (c == 'l') {
*login_sh = 1; /* -l or +l == --login */
continue;
}
/* bash does not accept +-login, we also won't */
if (val && (c == '-')) { /* long options */
if (strcmp(p, "login") == 0) {
*login_sh = 1;
}
break;
}
}
if (c == 'o') {
if (plus_minus_o(*argptr, val)) { if (plus_minus_o(*argptr, val)) {
/* it already printed err message */ /* it already printed err message */
return 1; /* error */ return 1; /* error */
} }
if (*argptr) if (*argptr)
argptr++; argptr++;
} else if (cmdline && (c == 'l')) { /* -l or +l == --login */
if (login_sh)
*login_sh = 1;
/* bash does not accept +-login, we also won't */
} else if (cmdline && val && (c == '-')) { /* long options */
if (strcmp(p, "login") == 0) {
if (login_sh)
*login_sh = 1;
}
break;
} else { } else {
setoption(c, val); setoption(c, val);
} }
@ -11227,7 +11261,7 @@ setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
return showvars(nullstr, 0, VUNSET); return showvars(nullstr, 0, VUNSET);
INT_OFF; INT_OFF;
retval = options(/*cmdline:*/ 0, NULL); retval = options(/*login_sh:*/ NULL);
if (retval == 0) { /* if no parse error... */ if (retval == 0) { /* if no parse error... */
optschanged(); optschanged();
if (*argptr != NULL) { if (*argptr != NULL) {
@ -13685,7 +13719,8 @@ helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
static int FAST_FUNC static int FAST_FUNC
historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
{ {
show_history(line_input_state); if (line_input_state)
show_history(line_input_state);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
#endif #endif
@ -14001,7 +14036,8 @@ exitshell(void)
int status; int status;
#if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
save_history(line_input_state); if (line_input_state)
save_history(line_input_state);
#endif #endif
status = exitstatus; status = exitstatus;
TRACE(("pid %d, exitshell(%d)\n", getpid(), status)); TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
@ -14123,7 +14159,7 @@ procargs(char **argv)
argptr = xargv; argptr = xargv;
for (i = 0; i < NOPTS; i++) for (i = 0; i < NOPTS; i++)
optlist[i] = 2; optlist[i] = 2;
if (options(/*cmdline:*/ 1, &login_sh)) { if (options(&login_sh)) {
/* it already printed err message */ /* it already printed err message */
raise_exception(EXERROR); raise_exception(EXERROR);
} }
@ -14249,9 +14285,6 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
monitor(4, etext, profile_buf, sizeof(profile_buf), 50); monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
#endif #endif
#if ENABLE_FEATURE_EDITING
line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
#endif
state = 0; state = 0;
if (setjmp(jmploc.loc)) { if (setjmp(jmploc.loc)) {
smallint e; smallint e;