From 3beab83e4f7f4213c185737e95dc4895f0059dd6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 7 Apr 2013 18:16:58 +0200 Subject: hush: fix for "while false && true; do echo BUG; break; done". closes 6170 function old new delta run_list 959 941 -18 Signed-off-by: Denys Vlasenko --- shell/hush.c | 19 +++++++++---------- shell/hush_test/hush-misc/while4.right | 1 + shell/hush_test/hush-misc/while4.tests | 6 ++++++ 3 files changed, 16 insertions(+), 10 deletions(-) create mode 100644 shell/hush_test/hush-misc/while4.right create mode 100755 shell/hush_test/hush-misc/while4.tests (limited to 'shell') diff --git a/shell/hush.c b/shell/hush.c index b23325725..1d421dc38 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -7354,7 +7354,7 @@ static int run_list(struct pipe *pi) * and we should not execute CMD */ debug_printf_exec("skipped cmd because of || or &&\n"); last_followup = pi->followup; - continue; + goto dont_check_jobs_but_continue; } } last_followup = pi->followup; @@ -7493,8 +7493,10 @@ static int run_list(struct pipe *pi) G.flag_break_continue = 0; /* else: e.g. "continue 2" should *break* once, *then* continue */ } /* else: "while... do... { we are here (innermost list is not a loop!) };...done" */ - if (G.depth_break_continue != 0 || fbc == BC_BREAK) - goto check_jobs_and_break; + if (G.depth_break_continue != 0 || fbc == BC_BREAK) { + checkjobs(NULL); + break; + } /* "continue": simulate end of loop */ rword = RES_DONE; continue; @@ -7502,7 +7504,6 @@ static int run_list(struct pipe *pi) #endif #if ENABLE_HUSH_FUNCTIONS if (G.flag_return_in_progress == 1) { - /* same as "goto check_jobs_and_break" */ checkjobs(NULL); break; } @@ -7544,6 +7545,9 @@ static int run_list(struct pipe *pi) if (rword == RES_IF || rword == RES_ELIF) cond_code = rcode; #endif + check_jobs_and_continue: + checkjobs(NULL); + dont_check_jobs_but_continue: ; #if ENABLE_HUSH_LOOPS /* Beware of "while false; true; do ..."! */ if (pi->next @@ -7555,22 +7559,17 @@ static int run_list(struct pipe *pi) /* "while false; do...done" - exitcode 0 */ G.last_exitcode = rcode = EXIT_SUCCESS; debug_printf_exec(": while expr is false: breaking (exitcode:EXIT_SUCCESS)\n"); - goto check_jobs_and_break; + break; } } if (rword == RES_UNTIL) { if (!rcode) { debug_printf_exec(": until expr is true: breaking\n"); - check_jobs_and_break: - checkjobs(NULL); break; } } } #endif - - check_jobs_and_continue: - checkjobs(NULL); } /* for (pi) */ #if ENABLE_HUSH_JOB diff --git a/shell/hush_test/hush-misc/while4.right b/shell/hush_test/hush-misc/while4.right new file mode 100644 index 000000000..7b24a35ff --- /dev/null +++ b/shell/hush_test/hush-misc/while4.right @@ -0,0 +1 @@ +Ok:0 diff --git a/shell/hush_test/hush-misc/while4.tests b/shell/hush_test/hush-misc/while4.tests new file mode 100755 index 000000000..ba80e603a --- /dev/null +++ b/shell/hush_test/hush-misc/while4.tests @@ -0,0 +1,6 @@ +false +while false && echo Not reached; do + echo BUG + break +done +echo Ok:$? -- cgit v1.2.3-55-g6feb From d96ffda62e9f9c88a6e43dc1926c5b775a611166 Mon Sep 17 00:00:00 2001 From: Flemming Madsen Date: Sun, 7 Apr 2013 18:47:24 +0200 Subject: ash,hush: history builtin function old new delta show_history - 39 +39 builtin_history - 16 +16 historycmd - 13 +13 bltins1 312 324 +12 builtintab 336 344 +8 popstring 134 140 +6 hush_main 1048 1046 -2 ash_main 1398 1396 -2 size_from_HISTFILESIZE 44 40 -4 ------------------------------------------------------------------------------ (add/remove: 3/0 grow/shrink: 3/3 up/down: 94/-8) Total: 86 bytes Signed-off-by: Flemming Madsen Signed-off-by: Denys Vlasenko --- include/libbb.h | 3 ++- libbb/lineedit.c | 16 ++++++++++++++-- shell/ash.c | 15 +++++++++++++++ shell/hush.c | 14 ++++++++++++++ 4 files changed, 45 insertions(+), 3 deletions(-) (limited to 'shell') diff --git a/include/libbb.h b/include/libbb.h index 6dd4d7cae..b5d1156ae 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1436,7 +1436,7 @@ void read_key_ungets(char *buffer, const char *str, unsigned len) FAST_FUNC; /* It's NOT just ENABLEd or disabled. It's a number: */ # if defined CONFIG_FEATURE_EDITING_HISTORY && CONFIG_FEATURE_EDITING_HISTORY > 0 # define MAX_HISTORY (CONFIG_FEATURE_EDITING_HISTORY + 0) -unsigned size_from_HISTFILESIZE(const char *hp); +unsigned size_from_HISTFILESIZE(const char *hp) FAST_FUNC; # else # define MAX_HISTORY 0 # endif @@ -1478,6 +1478,7 @@ line_input_t *new_line_input_t(int flags) FAST_FUNC; * >0 length of input string, including terminating '\n' */ int read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout) FAST_FUNC; +void show_history(const line_input_t *st) FAST_FUNC; # if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT void save_history(line_input_t *st); # endif diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 93ab86426..1313dd5d9 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -1254,7 +1254,7 @@ line_input_t* FAST_FUNC new_line_input_t(int flags) #if MAX_HISTORY > 0 -unsigned size_from_HISTFILESIZE(const char *hp) +unsigned FAST_FUNC size_from_HISTFILESIZE(const char *hp) { int size = MAX_HISTORY; if (hp) { @@ -1309,6 +1309,17 @@ static int get_next_history(void) return 0; } +/* Lists command history. Used by shell 'history' builtins */ +void FAST_FUNC show_history(const line_input_t *st) +{ + int i; + + if (!st) + return; + for (i = 0; i < st->cnt_history; i++) + printf("%4d %s\n", i, st->history[i]); +} + # if ENABLE_FEATURE_EDITING_SAVEHISTORY /* We try to ensure that concurrent additions to the history * do not overwrite each other. @@ -2749,8 +2760,9 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman free(command_ps); #endif - if (command_len > 0) + if (command_len > 0) { remember_in_history(command); + } if (break_out > 0) { command[command_len++] = '\n'; diff --git a/shell/ash.c b/shell/ash.c index edcb7c028..6af14f551 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -9033,6 +9033,9 @@ static int getoptscmd(int, char **) FAST_FUNC; #if !ENABLE_FEATURE_SH_EXTRA_QUIET static int helpcmd(int, char **) FAST_FUNC; #endif +#if MAX_HISTORY +static int historycmd(int, char **) FAST_FUNC; +#endif #if ENABLE_SH_MATH_SUPPORT static int letcmd(int, char **) FAST_FUNC; #endif @@ -9106,6 +9109,9 @@ static const struct builtincmd builtintab[] = { #if !ENABLE_FEATURE_SH_EXTRA_QUIET { BUILTIN_NOSPEC "help" , helpcmd }, #endif +#if MAX_HISTORY + { BUILTIN_NOSPEC "history" , historycmd }, +#endif #if JOBS { BUILTIN_REGULAR "jobs" , jobscmd }, { BUILTIN_REGULAR "kill" , killcmd }, @@ -12621,6 +12627,15 @@ helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) } #endif /* FEATURE_SH_EXTRA_QUIET */ +#if MAX_HISTORY +static int FAST_FUNC +historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) +{ + show_history(line_input_state); + return EXIT_SUCCESS; +} +#endif + /* * The export and readonly commands. */ diff --git a/shell/hush.c b/shell/hush.c index 1d421dc38..7cebe1784 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -850,6 +850,9 @@ static int builtin_jobs(char **argv) FAST_FUNC; #if ENABLE_HUSH_HELP static int builtin_help(char **argv) FAST_FUNC; #endif +#if MAX_HISTORY +static int builtin_history(char **argv) FAST_FUNC; +#endif #if ENABLE_HUSH_LOCAL static int builtin_local(char **argv) FAST_FUNC; #endif @@ -919,6 +922,9 @@ static const struct built_in_command bltins1[] = { #if ENABLE_HUSH_HELP BLTIN("help" , builtin_help , NULL), #endif +#if MAX_HISTORY + BLTIN("history" , builtin_history , "Show command history"), +#endif #if ENABLE_HUSH_JOB BLTIN("jobs" , builtin_jobs , "List jobs"), #endif @@ -8627,6 +8633,14 @@ static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM) } #endif +#if MAX_HISTORY +static int FAST_FUNC builtin_history(char **argv UNUSED_PARAM) +{ + show_history(G.line_input_state); + return EXIT_SUCCESS; +} +#endif + #if ENABLE_HUSH_JOB static int FAST_FUNC builtin_jobs(char **argv UNUSED_PARAM) { -- cgit v1.2.3-55-g6feb From ff463a885d7dbcea5493074cae498d58a5459539 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 12 May 2013 02:45:23 +0200 Subject: hush: fix build failure if FEATURE_EDITING=y && !HUSH_INTERACTIVE Signed-off-by: Denys Vlasenko --- shell/hush.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'shell') diff --git a/shell/hush.c b/shell/hush.c index 7cebe1784..1a2603e3b 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -850,7 +850,7 @@ static int builtin_jobs(char **argv) FAST_FUNC; #if ENABLE_HUSH_HELP static int builtin_help(char **argv) FAST_FUNC; #endif -#if MAX_HISTORY +#if MAX_HISTORY && ENABLE_FEATURE_EDITING static int builtin_history(char **argv) FAST_FUNC; #endif #if ENABLE_HUSH_LOCAL @@ -922,7 +922,7 @@ static const struct built_in_command bltins1[] = { #if ENABLE_HUSH_HELP BLTIN("help" , builtin_help , NULL), #endif -#if MAX_HISTORY +#if MAX_HISTORY && ENABLE_FEATURE_EDITING BLTIN("history" , builtin_history , "Show command history"), #endif #if ENABLE_HUSH_JOB @@ -8633,7 +8633,7 @@ static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM) } #endif -#if MAX_HISTORY +#if MAX_HISTORY && ENABLE_FEATURE_EDITING static int FAST_FUNC builtin_history(char **argv UNUSED_PARAM) { show_history(G.line_input_state); -- cgit v1.2.3-55-g6feb From 3e7ecb179b193bf17323c975890eed1d025f7e4c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 2 Jul 2013 17:30:23 +0200 Subject: unicode: check $LC_ALL to detect Unicode mode, not only $LANG Signed-off-by: Denys Vlasenko --- libbb/unicode.c | 14 ++++++++++---- shell/ash.c | 6 +++++- shell/hush.c | 4 +++- 3 files changed, 18 insertions(+), 6 deletions(-) (limited to 'shell') diff --git a/libbb/unicode.c b/libbb/unicode.c index 99dc1dfa6..c1e3966fe 100644 --- a/libbb/unicode.c +++ b/libbb/unicode.c @@ -39,8 +39,11 @@ void FAST_FUNC reinit_unicode(const char *LANG) void FAST_FUNC init_unicode(void) { - if (unicode_status == UNICODE_UNKNOWN) - reinit_unicode(getenv("LANG")); + if (unicode_status == UNICODE_UNKNOWN) { + char *s = getenv("LC_ALL"); + if (!s) s = getenv("LANG"); + reinit_unicode(s); + } } #else @@ -58,8 +61,11 @@ void FAST_FUNC reinit_unicode(const char *LANG) void FAST_FUNC init_unicode(void) { - if (unicode_status == UNICODE_UNKNOWN) - reinit_unicode(getenv("LANG")); + if (unicode_status == UNICODE_UNKNOWN) { + char *s = getenv("LC_ALL"); + if (!s) s = getenv("LANG"); + reinit_unicode(s); + } } # endif diff --git a/shell/ash.c b/shell/ash.c index 6af14f551..90f222467 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -9657,7 +9657,11 @@ preadfd(void) * _during_ shell execution, not only if it was set when * shell was started. Therefore, re-check LANG every time: */ - reinit_unicode(lookupvar("LANG")); + { + const char *s = lookupvar("LC_ALL"); + if (!s) s = lookupvar("LANG"); + reinit_unicode(s); + } nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout); if (nr == 0) { /* Ctrl+C pressed */ diff --git a/shell/hush.c b/shell/hush.c index 1a2603e3b..1fa84dc4f 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -2044,7 +2044,9 @@ static void get_user_input(struct in_str *i) * _during_ shell execution, not only if it was set when * shell was started. Therefore, re-check LANG every time: */ - reinit_unicode(get_local_var_value("LANG")); + const char *s = get_local_var_value("LC_ALL"); + if (!s) s = get_local_var_value("LANG"); + reinit_unicode(s); G.flag_SIGINT = 0; /* buglet: SIGINT will not make new prompt to appear _at once_, -- cgit v1.2.3-55-g6feb From 2301d127a2676303eac563e7932c03d9d72c446e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 5 Jul 2013 22:00:57 +0200 Subject: unicode: check $LC_CTYPE too to detect Unicode mode Signed-off-by: Denys Vlasenko --- Config.in | 5 +++-- libbb/unicode.c | 8 ++++++++ shell/ash.c | 1 + shell/hush.c | 1 + 4 files changed, 13 insertions(+), 2 deletions(-) (limited to 'shell') diff --git a/Config.in b/Config.in index 03c2d032f..2c4be2e9f 100644 --- a/Config.in +++ b/Config.in @@ -161,12 +161,13 @@ config UNICODE_USING_LOCALE Internal implementation is smaller. config FEATURE_CHECK_UNICODE_IN_ENV - bool "Check $LANG environment variable" + bool "Check $LC_ALL, $LC_CTYPE and $LANG environment variables" default n depends on UNICODE_SUPPORT && !UNICODE_USING_LOCALE help With this option on, Unicode support is activated - only if LANG variable has the value of the form "xxxx.utf8" + only if locale-related variables have the value of the form + "xxxx.utf8" Otherwise, Unicode support will be always enabled and active. diff --git a/libbb/unicode.c b/libbb/unicode.c index c1e3966fe..35e88d307 100644 --- a/libbb/unicode.c +++ b/libbb/unicode.c @@ -39,8 +39,15 @@ void FAST_FUNC reinit_unicode(const char *LANG) void FAST_FUNC init_unicode(void) { + /* Some people set only $LC_CTYPE, not $LC_ALL, because they want + * only Unicode to be activated on their system, not the whole + * shebang of wrong decimal points, strange date formats and so on. + * + * TODO? Maybe we should use LC_CTYPE instead of LC_ALL in setlocale()? + */ if (unicode_status == UNICODE_UNKNOWN) { char *s = getenv("LC_ALL"); + if (!s) s = getenv("LC_CTYPE"); if (!s) s = getenv("LANG"); reinit_unicode(s); } @@ -63,6 +70,7 @@ void FAST_FUNC init_unicode(void) { if (unicode_status == UNICODE_UNKNOWN) { char *s = getenv("LC_ALL"); + if (!s) s = getenv("LC_CTYPE"); if (!s) s = getenv("LANG"); reinit_unicode(s); } diff --git a/shell/ash.c b/shell/ash.c index 90f222467..d696bbdac 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -9659,6 +9659,7 @@ preadfd(void) */ { const char *s = lookupvar("LC_ALL"); + if (!s) s = lookupvar("LC_CTYPE"); if (!s) s = lookupvar("LANG"); reinit_unicode(s); } diff --git a/shell/hush.c b/shell/hush.c index 1fa84dc4f..fc9b89b55 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -2045,6 +2045,7 @@ static void get_user_input(struct in_str *i) * shell was started. Therefore, re-check LANG every time: */ const char *s = get_local_var_value("LC_ALL"); + if (!s) s = get_local_var_value("LC_CTYPE"); if (!s) s = get_local_var_value("LANG"); reinit_unicode(s); -- cgit v1.2.3-55-g6feb From e95738f63578c83be97a3236cd00510ef9375016 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 8 Jul 2013 03:13:08 +0200 Subject: typo fix in comment Signed-off-by: Denys Vlasenko --- shell/hush.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shell') diff --git a/shell/hush.c b/shell/hush.c index fc9b89b55..912ecf15f 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -1389,7 +1389,7 @@ static void restore_G_args(save_arg_t *sv, char **argv) * are set to '' (ignore) are NOT reset to defaults. We do the same. * * Problem: the above approach makes it unwieldy to catch signals while - * we are in read builtin, of while we read commands from stdin: + * we are in read builtin, or while we read commands from stdin: * masked signals are not visible! * * New implementation -- cgit v1.2.3-55-g6feb From 25ce3ee9f362de889aa3786128563af0c5d1b934 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 14 Jul 2013 01:23:06 +0200 Subject: typo fix in comment Signed-off-by: Denys Vlasenko --- shell/shell_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shell') diff --git a/shell/shell_common.c b/shell/shell_common.c index 0051f21d9..57297155e 100644 --- a/shell/shell_common.c +++ b/shell/shell_common.c @@ -37,7 +37,7 @@ int FAST_FUNC is_well_formed_var_name(const char *s, char terminator) /* read builtin */ -/* Needs to be interruptible: shell mush handle traps and shell-special signals +/* Needs to be interruptible: shell must handle traps and shell-special signals * while inside read. To implement this, be sure to not loop on EINTR * and return errno == EINTR reliably. */ -- cgit v1.2.3-55-g6feb