aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c36
-rw-r--r--shell/ash_test/ash-vars/var_bash_repl_empty_var.right1
-rwxr-xr-xshell/ash_test/ash-vars/var_bash_repl_empty_var.tests2
-rw-r--r--shell/hush.c24
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 */