diff options
Diffstat (limited to 'shell')
-rw-r--r-- | shell/ash.c | 36 | ||||
-rw-r--r-- | shell/ash_test/ash-vars/var_bash_repl_empty_var.right | 1 | ||||
-rwxr-xr-x | shell/ash_test/ash-vars/var_bash_repl_empty_var.tests | 2 | ||||
-rw-r--r-- | shell/hush.c | 24 |
4 files changed, 37 insertions, 26 deletions
diff --git a/shell/ash.c b/shell/ash.c index f16d7fb6a..1aead6df4 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -314,9 +314,12 @@ typedef long arith_t; /* ============ Shell options */ +/* If you add/change options hare, update --help text too */ static const char *const optletters_optnames[] = { "e" "errexit", "f" "noglob", +/* bash has '-o ignoreeof', but no short synonym -I for it */ +/* (in bash, set -I disables invisible variables (what's that?)) */ "I" "ignoreeof", /* The below allowed this invocation: * ash -c 'set -i; echo $-; sleep 5; echo $-' @@ -325,9 +328,10 @@ static const char *const optletters_optnames[] = { * In our code, this is denoted by empty long name: */ "i" "", +/* (removing "i" altogether would remove it from "$-", not good) */ "m" "monitor", "n" "noexec", -/* Ditto: bash has no "set -s" */ +/* Ditto: bash has no "set -s", "set -c" */ "s" "", "c" "", "x" "xtrace", @@ -7011,7 +7015,8 @@ subevalvar(char *start, char *str, int strloc, slash_pos = -1; if (repl) { slash_pos = expdest - ((char *)stackblock() + strloc); - STPUTC('/', expdest); + if (!(flag & EXP_DISCARD)) + STPUTC('/', expdest); //bb_error_msg("repl+1:'%s'", repl + 1); p = argstr(repl + 1, (flag & EXP_DISCARD) | EXP_TILDE); /* EXP_TILDE: echo "${v/x/~}" expands ~ ! */ *repl = '/'; @@ -7173,7 +7178,7 @@ subevalvar(char *start, char *str, int strloc, len = 0; idx = startp; end = str - 1; - while (idx < end) { + while (idx <= end) { try_to_match: loc = scanright(idx, rmesc, rmescend, str, quotes, 1); //bb_error_msg("scanright('%s'):'%s'", str, loc); @@ -7181,6 +7186,8 @@ subevalvar(char *start, char *str, int strloc, /* No match, advance */ char *restart_detect = stackblock(); skip_matching: + if (idx >= end) + break; STPUTC(*idx, expdest); if (quotes && (unsigned char)*idx == CTLESC) { idx++; @@ -7193,8 +7200,6 @@ subevalvar(char *start, char *str, int strloc, len++; rmesc++; /* continue; - prone to quadratic behavior, smarter code: */ - if (idx >= end) - break; if (str[0] == '*') { /* Pattern is "*foo". If "*foo" does not match "long_string", * it would never match "ong_string" etc, no point in trying. @@ -11371,10 +11376,10 @@ static void FAST_FUNC change_epoch(struct var *vepoch, const char *fmt) { struct timeval tv; - char buffer[sizeof("%lu.nnnnnn") + sizeof(long)*3]; + char buffer[sizeof("%llu.nnnnnn") + sizeof(long long)*3]; - gettimeofday(&tv, NULL); - sprintf(buffer, fmt, (unsigned long)tv.tv_sec, (unsigned)tv.tv_usec); + xgettimeofday(&tv); + sprintf(buffer, fmt, (unsigned long long)tv.tv_sec, (unsigned)tv.tv_usec); setvar(vepoch->var_text, buffer, VNOFUNC); vepoch->flags &= ~VNOFUNC; } @@ -11382,13 +11387,13 @@ change_epoch(struct var *vepoch, const char *fmt) static void FAST_FUNC change_seconds(const char *value UNUSED_PARAM) { - change_epoch(&vepochs, "%lu"); + change_epoch(&vepochs, "%llu"); } static void FAST_FUNC change_realtime(const char *value UNUSED_PARAM) { - change_epoch(&vepochr, "%lu.%06u"); + change_epoch(&vepochr, "%llu.%06u"); } #endif @@ -14265,7 +14270,8 @@ init(void) //usage:#define ash_trivial_usage -//usage: "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS] / -s [ARGS]]" +//usage: "[-il] [-/+Cabefmnuvx] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS] / -s [ARGS]]" +//////// comes from ^^^^^^^^^^optletters //usage:#define ash_full_usage "\n\n" //usage: "Unix shell interpreter" @@ -14312,9 +14318,9 @@ procargs(char **argv) } if (mflag == 2) mflag = iflag; + /* Unset options which weren't explicitly set or unset */ for (i = 0; i < NOPTS; i++) - if (optlist[i] == 2) - optlist[i] = 0; + optlist[i] &= 1; /* same effect as "if (optlist[i] == 2) optlist[i] = 0;" */ #if DEBUG == 2 debug = 1; #endif @@ -14499,7 +14505,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) if (sflag || minusc == NULL) { #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY - if (iflag) { + if (line_input_state) { const char *hp = lookupvar("HISTFILE"); if (!hp) { hp = lookupvar("HOME"); @@ -14513,7 +14519,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) } } if (hp) - line_input_state->hist_file = hp; + line_input_state->hist_file = xstrdup(hp); # if ENABLE_FEATURE_SH_HISTFILESIZE hp = lookupvar("HISTFILESIZE"); line_input_state->max_history = size_from_HISTFILESIZE(hp); diff --git a/shell/ash_test/ash-vars/var_bash_repl_empty_var.right b/shell/ash_test/ash-vars/var_bash_repl_empty_var.right index 892916783..a8d1a3bef 100644 --- a/shell/ash_test/ash-vars/var_bash_repl_empty_var.right +++ b/shell/ash_test/ash-vars/var_bash_repl_empty_var.right @@ -1,2 +1,3 @@ +w Ok:0 diff --git a/shell/ash_test/ash-vars/var_bash_repl_empty_var.tests b/shell/ash_test/ash-vars/var_bash_repl_empty_var.tests index 73a43d38e..22aaba560 100755 --- a/shell/ash_test/ash-vars/var_bash_repl_empty_var.tests +++ b/shell/ash_test/ash-vars/var_bash_repl_empty_var.tests @@ -1,3 +1,5 @@ +unset v +echo ${v/*/w} v='' echo ${v/*/w} echo Ok:$? diff --git a/shell/hush.c b/shell/hush.c index 9fead37da..5eb6fa396 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -1027,7 +1027,7 @@ struct globals { struct sigaction sa; char optstring_buf[sizeof("eixcs")]; #if BASH_EPOCH_VARS - char epoch_buf[sizeof("%lu.nnnnnn") + sizeof(long)*3]; + char epoch_buf[sizeof("%llu.nnnnnn") + sizeof(long long)*3]; #endif #if ENABLE_FEATURE_EDITING char user_input_buf[CONFIG_FEATURE_EDITING_MAX_LEN]; @@ -2277,13 +2277,13 @@ static const char* FAST_FUNC get_local_var_value(const char *name) { const char *fmt = NULL; if (strcmp(name, "EPOCHSECONDS") == 0) - fmt = "%lu"; + fmt = "%llu"; else if (strcmp(name, "EPOCHREALTIME") == 0) - fmt = "%lu.%06u"; + fmt = "%llu.%06u"; if (fmt) { struct timeval tv; - gettimeofday(&tv, NULL); - sprintf(G.epoch_buf, fmt, (unsigned long)tv.tv_sec, + xgettimeofday(&tv); + sprintf(G.epoch_buf, fmt, (unsigned long long)tv.tv_sec, (unsigned)tv.tv_usec); return G.epoch_buf; } @@ -2692,7 +2692,7 @@ static int get_user_input(struct in_str *i) * Without check_and_run_traps, handler never runs. */ check_and_run_traps(); - fputs(prompt_str, stdout); + fputs_stdout(prompt_str); fflush_all(); } r = hfgetc(i->file); @@ -10163,7 +10163,8 @@ int hush_main(int argc, char **argv) /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */ flags = (argv[0] && argv[0][0] == '-') ? OPT_login : 0; while (1) { - int opt = getopt(argc, argv, "+cexinsl" + int opt = getopt(argc, argv, "+" /* stop at 1st non-option */ + "cexinsl" #if !BB_MMU "<:$:R:V:" # if ENABLE_HUSH_FUNCTIONS @@ -10255,12 +10256,13 @@ int hush_main(int argc, char **argv) } # endif #endif - case 'n': - case 'x': - case 'e': + /*case '?': invalid option encountered (set_mode('?') will fail) */ + /*case 'n':*/ + /*case 'x':*/ + /*case 'e':*/ + default: if (set_mode(1, opt, NULL) == 0) /* no error */ break; - default: bb_show_usage(); } } /* option parsing loop */ |