aboutsummaryrefslogtreecommitdiff
path: root/shell
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 /shell
parent6eb6e6a1e9d6e7d4dd154014ce404ec1c8175fb2 (diff)
downloadbusybox-897475ab023040efed9f199af5daffe43451c1d2.tar.gz
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>
Diffstat (limited to 'shell')
-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[] = {
"e" "errexit",
"f" "noglob",
"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",
"m" "monitor",
"n" "noexec",
+/* Ditto: bash has no "set -s" and "set -o stdin" */
"s" "stdin",
"x" "xtrace",
"v" "verbose",
@@ -334,10 +341,25 @@ static const char *const optletters_optnames[] = {
,"\0" "debug"
#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 optnames(n) (optletters_optnames[n] + 1)
+
enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
@@ -9514,8 +9536,8 @@ setinteractive(int on)
setsignal(SIGINT);
setsignal(SIGQUIT);
setsignal(SIGTERM);
-#if !ENABLE_FEATURE_SH_EXTRA_QUIET
if (is_interactive > 1) {
+#if !ENABLE_FEATURE_SH_EXTRA_QUIET
/* Looks like they want an interactive shell */
static smallint did_banner;
@@ -9529,8 +9551,12 @@ setinteractive(int on)
);
did_banner = 1;
}
- }
#endif
+#if ENABLE_FEATURE_EDITING
+ if (!line_input_state)
+ line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
+#endif
+ }
}
static void
@@ -9542,10 +9568,12 @@ optschanged(void)
setinteractive(iflag);
setjobctl(mflag);
#if ENABLE_FEATURE_EDITING_VI
- if (viflag)
- line_input_state->flags |= VI_MODE;
- else
- line_input_state->flags &= ~VI_MODE;
+ if (line_input_state) {
+ if (viflag)
+ line_input_state->flags |= VI_MODE;
+ else
+ line_input_state->flags &= ~VI_MODE;
+ }
#else
viflag = 0; /* forcibly keep the option off */
#endif
@@ -10519,13 +10547,11 @@ preadfd(void)
else {
# if ENABLE_ASH_IDLE_TIMEOUT
int timeout = -1;
- if (iflag) {
- const char *tmout_var = lookupvar("TMOUT");
- if (tmout_var) {
- timeout = atoi(tmout_var) * 1000;
- if (timeout <= 0)
- timeout = -1;
- }
+ const char *tmout_var = lookupvar("TMOUT");
+ if (tmout_var) {
+ timeout = atoi(tmout_var) * 1000;
+ if (timeout <= 0)
+ timeout = -1;
}
line_input_state->timeout = timeout;
# endif
@@ -11086,14 +11112,17 @@ setoption(int flag, int val)
ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
/* NOTREACHED */
}
+/* If login_sh is not NULL, we are called to parse command line opts,
+ * not "set -opts"
+ */
static int
-options(int cmdline, int *login_sh)
+options(int *login_sh)
{
char *p;
int val;
int c;
- if (cmdline)
+ if (login_sh)
minusc = NULL;
while ((p = *argptr) != NULL) {
c = *p++;
@@ -11104,7 +11133,7 @@ options(int cmdline, int *login_sh)
if (c == '-') {
val = 1;
if (p[0] == '\0' || LONE_DASH(p)) {
- if (!cmdline) {
+ if (!login_sh) {
/* "-" means turn off -x and -v */
if (p[0] == '\0')
xflag = vflag = 0;
@@ -11117,26 +11146,31 @@ options(int cmdline, int *login_sh)
}
/* first char was + or - */
while ((c = *p++) != '\0') {
- /* bash 3.2 indeed handles -c CMD and +c CMD the same */
- if (c == 'c' && cmdline) {
- minusc = p; /* command is after shell args */
- } else if (c == 'o') {
+ if (login_sh) {
+ /* bash 3.2 indeed handles -c CMD and +c CMD the same */
+ if (c == 'c') {
+ 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)) {
/* it already printed err message */
return 1; /* error */
}
if (*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 {
setoption(c, val);
}
@@ -11227,7 +11261,7 @@ setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
return showvars(nullstr, 0, VUNSET);
INT_OFF;
- retval = options(/*cmdline:*/ 0, NULL);
+ retval = options(/*login_sh:*/ NULL);
if (retval == 0) { /* if no parse error... */
optschanged();
if (*argptr != NULL) {
@@ -13685,7 +13719,8 @@ helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
static int FAST_FUNC
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;
}
#endif
@@ -14001,7 +14036,8 @@ exitshell(void)
int status;
#if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
- save_history(line_input_state);
+ if (line_input_state)
+ save_history(line_input_state);
#endif
status = exitstatus;
TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
@@ -14123,7 +14159,7 @@ procargs(char **argv)
argptr = xargv;
for (i = 0; i < NOPTS; i++)
optlist[i] = 2;
- if (options(/*cmdline:*/ 1, &login_sh)) {
+ if (options(&login_sh)) {
/* it already printed err message */
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);
#endif
-#if ENABLE_FEATURE_EDITING
- line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
-#endif
state = 0;
if (setjmp(jmploc.loc)) {
smallint e;