From f5018dac21df54647d0982ed4bebd0286d77cc56 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 6 Apr 2018 17:58:21 +0200 Subject: [PATCH] hush: fix "unset PS1/PS2", and put them into initial variable set "unset PS1/PS2" causes prompts to be empty strings function old new delta hush_main 1031 1089 +58 goto_new_line 27 33 +6 fgetc_interactive 244 245 +1 unset_local_var 155 149 -6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/1 up/down: 65/-6) Total: 59 bytes Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 3 ++- shell/hush.c | 64 ++++++++++++++++++++++++++---------------------- 2 files changed, 37 insertions(+), 30 deletions(-) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 678c4d29c..d5e92e84c 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -430,7 +430,8 @@ static void put_till_end_and_adv_cursor(void) static void goto_new_line(void) { put_till_end_and_adv_cursor(); - if (cmdedit_x != 0) + /* "cursor == 0" is only if prompt is "" and user input is empty */ + if (cursor == 0 || cmdedit_x != 0) bb_putchar('\n'); } diff --git a/shell/hush.c b/shell/hush.c index 971a16aff..34d905397 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -828,7 +828,7 @@ struct globals { * _AND_ if we decided to act interactively */ int interactive_fd; const char *PS1; - const char *PS2; + IF_FEATURE_EDITING_FANCY_PROMPT(const char *PS2;) # define G_interactive_fd (G.interactive_fd) #else # define G_interactive_fd 0 @@ -1394,7 +1394,7 @@ static void syntax_error_unexpected_ch(unsigned lineno UNUSED_PARAM, int ch) #endif -#if ENABLE_HUSH_INTERACTIVE +#if ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT static void cmdedit_update_prompt(void); #else # define cmdedit_update_prompt() ((void)0) @@ -2125,7 +2125,9 @@ static const char* FAST_FUNC get_local_var_value(const char *name) static void handle_changed_special_names(const char *name, unsigned name_len) { - if (name_len == 3 && name[0] == 'P' && name[1] == 'S') { + if (ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT + && name_len == 3 && name[0] == 'P' && name[1] == 'S' + ) { cmdedit_update_prompt(); return; } @@ -2305,9 +2307,6 @@ static int unset_local_var_len(const char *name, int name_len) struct variable *cur; struct variable **cur_pp; - if (!name) - return EXIT_SUCCESS; - cur_pp = &G.top_var; while ((cur = *cur_pp) != NULL) { if (strncmp(cur->varstr, name, name_len) == 0 @@ -2321,17 +2320,18 @@ static int unset_local_var_len(const char *name, int name_len) *cur_pp = cur->next; debug_printf_env("%s: unsetenv '%s'\n", __func__, cur->varstr); bb_unsetenv(cur->varstr); - - handle_changed_special_names(name, name_len); - if (!cur->max_len) free(cur->varstr); free(cur); - return EXIT_SUCCESS; + break; } cur_pp = &cur->next; } + + /* Handle "unset PS1" et al even if did not find the variable to unset */ + handle_changed_special_names(name, name_len); + return EXIT_SUCCESS; } @@ -2459,36 +2459,36 @@ static void reinit_unicode_for_hush(void) * \ * It exercises a lot of corner cases. */ +# if ENABLE_FEATURE_EDITING_FANCY_PROMPT static void cmdedit_update_prompt(void) { - if (ENABLE_FEATURE_EDITING_FANCY_PROMPT) { - G.PS1 = get_local_var_value("PS1"); - if (G.PS1 == NULL) - G.PS1 = "\\w \\$ "; - G.PS2 = get_local_var_value("PS2"); - } else { - G.PS1 = NULL; - } + G.PS1 = get_local_var_value("PS1"); + if (G.PS1 == NULL) + G.PS1 = ""; + G.PS2 = get_local_var_value("PS2"); if (G.PS2 == NULL) - G.PS2 = "> "; + G.PS2 = ""; } +# endif static const char *setup_prompt_string(int promptmode) { const char *prompt_str; + debug_printf("setup_prompt_string %d ", promptmode); - if (!ENABLE_FEATURE_EDITING_FANCY_PROMPT) { - /* Set up the prompt */ - if (promptmode == 0) { /* PS1 */ + + IF_FEATURE_EDITING_FANCY_PROMPT( prompt_str = G.PS2;) + IF_NOT_FEATURE_EDITING_FANCY_PROMPT(prompt_str = "> ";) + if (promptmode == 0) { /* PS1 */ + if (!ENABLE_FEATURE_EDITING_FANCY_PROMPT) { + /* No fancy prompts supported, (re)generate "CURDIR $ " by hand */ free((char*)G.PS1); /* bash uses $PWD value, even if it is set by user. * It uses current dir only if PWD is unset. * We always use current dir. */ G.PS1 = xasprintf("%s %c ", get_cwd(0), (geteuid() != 0) ? '$' : '#'); - prompt_str = G.PS1; - } else - prompt_str = G.PS2; - } else - prompt_str = (promptmode == 0) ? G.PS1 : G.PS2; + } + prompt_str = G.PS1; + } debug_printf("prompt_str '%s'\n", prompt_str); return prompt_str; } @@ -9207,6 +9207,14 @@ int hush_main(int argc, char **argv) /* Export PWD */ set_pwd_var(SETFLAG_EXPORT); +#if ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT + /* Set (but not export) PS1/2 unless already set */ + if (!get_local_var_value("PS1")) + set_local_var_from_halves("PS1", "\\w \\$ "); + if (!get_local_var_value("PS2")) + set_local_var_from_halves("PS2", "> "); +#endif + #if BASH_HOSTNAME_VAR /* Set (but not export) HOSTNAME unless already set */ if (!get_local_var_value("HOSTNAME")) { @@ -9245,8 +9253,6 @@ int hush_main(int argc, char **argv) * OPTERR=1 * OPTIND=1 * IFS=$' \t\n' - * PS1='\s-\v\$ ' - * PS2='> ' * PS4='+ ' */ #endif