diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2025-08-03 01:02:55 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2025-08-03 01:26:25 +0200 |
| commit | cdbb6957f1bfafbcbe7e9abbb79979c8cd29881c (patch) | |
| tree | 5c68d0f57b5466f12f26900001dd034202594684 /shell | |
| parent | e591316e020258d07dc987c5f2f4b7a03d786ddd (diff) | |
| download | busybox-w32-cdbb6957f1bfafbcbe7e9abbb79979c8cd29881c.tar.gz busybox-w32-cdbb6957f1bfafbcbe7e9abbb79979c8cd29881c.tar.bz2 busybox-w32-cdbb6957f1bfafbcbe7e9abbb79979c8cd29881c.zip | |
hush: don't save history in subshells; on NOMMU, don't be interactive on reexec
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/hush.c | 126 |
1 files changed, 72 insertions, 54 deletions
diff --git a/shell/hush.c b/shell/hush.c index 5707b4b31..5f4c0cca5 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
| @@ -930,6 +930,12 @@ struct globals { | |||
| 930 | # define G_flag_return_in_progress 0 | 930 | # define G_flag_return_in_progress 0 |
| 931 | #endif | 931 | #endif |
| 932 | smallint exiting; /* used to prevent EXIT trap recursion */ | 932 | smallint exiting; /* used to prevent EXIT trap recursion */ |
| 933 | #if !BB_MMU | ||
| 934 | smallint reexeced_on_NOMMU; | ||
| 935 | # define G_reexeced_on_NOMMU (G.reexeced_on_NOMMU) | ||
| 936 | #else | ||
| 937 | # define G_reexeced_on_NOMMU 0 | ||
| 938 | #endif | ||
| 933 | /* These support $? */ | 939 | /* These support $? */ |
| 934 | smalluint last_exitcode; | 940 | smalluint last_exitcode; |
| 935 | smalluint expand_exitcode; | 941 | smalluint expand_exitcode; |
| @@ -2105,7 +2111,9 @@ static const char* FAST_FUNC get_local_var_value(const char *name); | |||
| 2105 | static void save_history_run_exit_trap_and_exit(int exitcode) | 2111 | static void save_history_run_exit_trap_and_exit(int exitcode) |
| 2106 | { | 2112 | { |
| 2107 | #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT | 2113 | #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT |
| 2108 | if (G.line_input_state) { | 2114 | if (G.line_input_state |
| 2115 | && getpid() == G.root_pid /* exits in subshells do not save history */ | ||
| 2116 | ) { | ||
| 2109 | const char *hp; | 2117 | const char *hp; |
| 2110 | # if ENABLE_FEATURE_SH_HISTFILESIZE | 2118 | # if ENABLE_FEATURE_SH_HISTFILESIZE |
| 2111 | // in bash: | 2119 | // in bash: |
| @@ -10218,6 +10226,53 @@ static int run_and_free_list(struct pipe *pi) | |||
| 10218 | /* | 10226 | /* |
| 10219 | * Initialization and main | 10227 | * Initialization and main |
| 10220 | */ | 10228 | */ |
| 10229 | #if ENABLE_FEATURE_EDITING | ||
| 10230 | static void init_line_editing(void) | ||
| 10231 | { | ||
| 10232 | G.line_input_state = new_line_input_t(FOR_SHELL); | ||
| 10233 | # if ENABLE_FEATURE_TAB_COMPLETION | ||
| 10234 | G.line_input_state->get_exe_name = hush_command_name; | ||
| 10235 | # endif | ||
| 10236 | # if EDITING_HAS_sh_get_var | ||
| 10237 | G.line_input_state->sh_get_var = get_local_var_value; | ||
| 10238 | # endif | ||
| 10239 | # if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0 | ||
| 10240 | { | ||
| 10241 | const char *hp = get_local_var_value("HISTFILE"); | ||
| 10242 | if (!hp) { | ||
| 10243 | hp = get_local_var_value("HOME"); | ||
| 10244 | if (hp) { | ||
| 10245 | hp = concat_path_file(hp, ".hush_history"); | ||
| 10246 | /* Make HISTFILE set on exit (else history won't be saved) */ | ||
| 10247 | set_local_var_from_halves("HISTFILE", hp); | ||
| 10248 | } | ||
| 10249 | } else { | ||
| 10250 | hp = xstrdup(hp); | ||
| 10251 | } | ||
| 10252 | if (hp) { | ||
| 10253 | G.line_input_state->hist_file = hp; | ||
| 10254 | } | ||
| 10255 | # if ENABLE_FEATURE_SH_HISTFILESIZE | ||
| 10256 | hp = get_local_var_value("HISTSIZE"); | ||
| 10257 | /* Using HISTFILESIZE above to limit max_history would be WRONG: | ||
| 10258 | * users may set HISTFILESIZE=0 in their profile scripts | ||
| 10259 | * to prevent _saving_ of history files, but still want to have | ||
| 10260 | * non-zero history limit for in-memory list. | ||
| 10261 | */ | ||
| 10262 | // in bash, runtime history size is controlled by HISTSIZE (0=no history), | ||
| 10263 | // HISTFILESIZE controls on-disk history file size (in lines, 0=no history): | ||
| 10264 | G.line_input_state->max_history = size_from_HISTFILESIZE(hp); | ||
| 10265 | // HISTFILESIZE: "The shell sets the default value to the value of HISTSIZE after reading any startup files." | ||
| 10266 | // HISTSIZE: "The shell sets the default value to 500 after reading any startup files." | ||
| 10267 | // (meaning: if the value wasn't set after startup files, the default value is set as described above) | ||
| 10268 | # endif | ||
| 10269 | } | ||
| 10270 | # endif | ||
| 10271 | } | ||
| 10272 | #else | ||
| 10273 | # define init_line_editing() ((void)0) | ||
| 10274 | #endif | ||
| 10275 | |||
| 10221 | static void install_sighandlers(unsigned mask) | 10276 | static void install_sighandlers(unsigned mask) |
| 10222 | { | 10277 | { |
| 10223 | sighandler_t old_handler; | 10278 | sighandler_t old_handler; |
| @@ -10356,7 +10411,6 @@ static int set_mode(int state, char mode, const char *o_opt) | |||
| 10356 | int hush_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 10411 | int hush_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 10357 | int hush_main(int argc, char **argv) | 10412 | int hush_main(int argc, char **argv) |
| 10358 | { | 10413 | { |
| 10359 | pid_t cached_getpid; | ||
| 10360 | enum { | 10414 | enum { |
| 10361 | OPT_login = (1 << 0), | 10415 | OPT_login = (1 << 0), |
| 10362 | }; | 10416 | }; |
| @@ -10384,9 +10438,6 @@ int hush_main(int argc, char **argv) | |||
| 10384 | _exit(0); | 10438 | _exit(0); |
| 10385 | } | 10439 | } |
| 10386 | G.argv0_for_re_execing = argv[0]; | 10440 | G.argv0_for_re_execing = argv[0]; |
| 10387 | if (G.argv0_for_re_execing[0] == '-') | ||
| 10388 | /* reexeced hush should never be a login shell */ | ||
| 10389 | G.argv0_for_re_execing++; | ||
| 10390 | #endif | 10441 | #endif |
| 10391 | #if ENABLE_HUSH_TRAP | 10442 | #if ENABLE_HUSH_TRAP |
| 10392 | # if ENABLE_HUSH_FUNCTIONS | 10443 | # if ENABLE_HUSH_FUNCTIONS |
| @@ -10399,9 +10450,8 @@ int hush_main(int argc, char **argv) | |||
| 10399 | G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */ | 10450 | G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */ |
| 10400 | #endif | 10451 | #endif |
| 10401 | 10452 | ||
| 10402 | cached_getpid = getpid(); /* for tcsetpgrp() during init */ | 10453 | G.root_pid = getpid(); /* for $PID (NOMMU can override via -$HEXPID:HEXPPID:...) */ |
| 10403 | G.root_pid = cached_getpid; /* for $PID (NOMMU can override via -$HEXPID:HEXPPID:...) */ | 10454 | G.root_ppid = getppid(); /* for $PPID (NOMMU can override) */ |
| 10404 | G.root_ppid = getppid(); /* for $PPID (NOMMU can override) */ | ||
| 10405 | 10455 | ||
| 10406 | /* Deal with HUSH_VERSION */ | 10456 | /* Deal with HUSH_VERSION */ |
| 10407 | debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); | 10457 | debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); |
| @@ -10568,6 +10618,7 @@ int hush_main(int argc, char **argv) | |||
| 10568 | case '$': { | 10618 | case '$': { |
| 10569 | unsigned long long empty_trap_mask; | 10619 | unsigned long long empty_trap_mask; |
| 10570 | 10620 | ||
| 10621 | G.reexeced_on_NOMMU = 1; | ||
| 10571 | G.root_pid = bb_strtou(optarg, &optarg, 16); | 10622 | G.root_pid = bb_strtou(optarg, &optarg, 16); |
| 10572 | optarg++; | 10623 | optarg++; |
| 10573 | G.root_ppid = bb_strtou(optarg, &optarg, 16); | 10624 | G.root_ppid = bb_strtou(optarg, &optarg, 16); |
| @@ -10647,7 +10698,9 @@ int hush_main(int argc, char **argv) | |||
| 10647 | G.global_argv[0] = argv[0]; | 10698 | G.global_argv[0] = argv[0]; |
| 10648 | 10699 | ||
| 10649 | /* If we are login shell... */ | 10700 | /* If we are login shell... */ |
| 10650 | if (flags & OPT_login) { | 10701 | if (!G_reexeced_on_NOMMU /* reexeced hush should never be a login shell */ |
| 10702 | && (flags & OPT_login) | ||
| 10703 | ) { | ||
| 10651 | const char *hp = NULL; | 10704 | const char *hp = NULL; |
| 10652 | HFILE *input; | 10705 | HFILE *input; |
| 10653 | 10706 | ||
| @@ -10767,7 +10820,9 @@ int hush_main(int argc, char **argv) | |||
| 10767 | * Refer to Posix.2, the description of the 'sh' utility. | 10820 | * Refer to Posix.2, the description of the 'sh' utility. |
| 10768 | */ | 10821 | */ |
| 10769 | #if ENABLE_HUSH_JOB | 10822 | #if ENABLE_HUSH_JOB |
| 10770 | if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) { | 10823 | if (!G_reexeced_on_NOMMU |
| 10824 | && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) | ||
| 10825 | ) { | ||
| 10771 | G_saved_tty_pgrp = tcgetpgrp(STDIN_FILENO); | 10826 | G_saved_tty_pgrp = tcgetpgrp(STDIN_FILENO); |
| 10772 | debug_printf("saved_tty_pgrp:%d\n", G_saved_tty_pgrp); | 10827 | debug_printf("saved_tty_pgrp:%d\n", G_saved_tty_pgrp); |
| 10773 | if (G_saved_tty_pgrp < 0) | 10828 | if (G_saved_tty_pgrp < 0) |
| @@ -10813,57 +10868,18 @@ int hush_main(int argc, char **argv) | |||
| 10813 | * (bash, too, does this only if ctty is available) */ | 10868 | * (bash, too, does this only if ctty is available) */ |
| 10814 | bb_setpgrp(); /* is the same as setpgid(our_pid, our_pid); */ | 10869 | bb_setpgrp(); /* is the same as setpgid(our_pid, our_pid); */ |
| 10815 | /* Grab control of the terminal */ | 10870 | /* Grab control of the terminal */ |
| 10816 | tcsetpgrp(G_interactive_fd, cached_getpid); | 10871 | tcsetpgrp(G_interactive_fd, G.root_pid); |
| 10817 | } | 10872 | } |
| 10818 | enable_restore_tty_pgrp_on_exit(); | 10873 | enable_restore_tty_pgrp_on_exit(); |
| 10819 | 10874 | init_line_editing(); | |
| 10820 | # if ENABLE_FEATURE_EDITING | ||
| 10821 | G.line_input_state = new_line_input_t(FOR_SHELL); | ||
| 10822 | # if ENABLE_FEATURE_TAB_COMPLETION | ||
| 10823 | G.line_input_state->get_exe_name = hush_command_name; | ||
| 10824 | # endif | ||
| 10825 | # if EDITING_HAS_sh_get_var | ||
| 10826 | G.line_input_state->sh_get_var = get_local_var_value; | ||
| 10827 | # endif | ||
| 10828 | # endif | ||
| 10829 | # if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0 | ||
| 10830 | { | ||
| 10831 | const char *hp = get_local_var_value("HISTFILE"); | ||
| 10832 | if (!hp) { | ||
| 10833 | hp = get_local_var_value("HOME"); | ||
| 10834 | if (hp) { | ||
| 10835 | hp = concat_path_file(hp, ".hush_history"); | ||
| 10836 | /* Make HISTFILE set on exit (else history won't be saved) */ | ||
| 10837 | set_local_var_from_halves("HISTFILE", hp); | ||
| 10838 | } | ||
| 10839 | } else { | ||
| 10840 | hp = xstrdup(hp); | ||
| 10841 | } | ||
| 10842 | if (hp) { | ||
| 10843 | G.line_input_state->hist_file = hp; | ||
| 10844 | } | ||
| 10845 | # if ENABLE_FEATURE_SH_HISTFILESIZE | ||
| 10846 | hp = get_local_var_value("HISTSIZE"); | ||
| 10847 | /* Using HISTFILESIZE above to limit max_history would be WRONG: | ||
| 10848 | * users may set HISTFILESIZE=0 in their profile scripts | ||
| 10849 | * to prevent _saving_ of history files, but still want to have | ||
| 10850 | * non-zero history limit for in-memory list. | ||
| 10851 | */ | ||
| 10852 | // in bash, runtime history size is controlled by HISTSIZE (0=no history), | ||
| 10853 | // HISTFILESIZE controls on-disk history file size (in lines, 0=no history): | ||
| 10854 | G.line_input_state->max_history = size_from_HISTFILESIZE(hp); | ||
| 10855 | // HISTFILESIZE: "The shell sets the default value to the value of HISTSIZE after reading any startup files." | ||
| 10856 | // HISTSIZE: "The shell sets the default value to 500 after reading any startup files." | ||
| 10857 | // (meaning: if the value wasn't set after startup files, the default value is set as described above) | ||
| 10858 | # endif | ||
| 10859 | } | ||
| 10860 | # endif | ||
| 10861 | } else { | 10875 | } else { |
| 10862 | install_special_sighandlers(); | 10876 | install_special_sighandlers(); |
| 10863 | } | 10877 | } |
| 10864 | #elif ENABLE_HUSH_INTERACTIVE | 10878 | #elif ENABLE_HUSH_INTERACTIVE |
| 10865 | /* No job control compiled in, only prompt/line editing */ | 10879 | /* No job control compiled in, only prompt/line editing */ |
| 10866 | if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) { | 10880 | if (!G_reexeced_on_NOMMU |
| 10881 | && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) | ||
| 10882 | ) { | ||
| 10867 | G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254); | 10883 | G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254); |
| 10868 | if (G_interactive_fd < 0) { | 10884 | if (G_interactive_fd < 0) { |
| 10869 | /* try to dup to any fd */ | 10885 | /* try to dup to any fd */ |
| @@ -10872,6 +10888,8 @@ int hush_main(int argc, char **argv) | |||
| 10872 | /* give up */ | 10888 | /* give up */ |
| 10873 | G_interactive_fd = 0; | 10889 | G_interactive_fd = 0; |
| 10874 | } | 10890 | } |
| 10891 | if (G_interactive_fd) | ||
| 10892 | init_line_editing(); | ||
| 10875 | } | 10893 | } |
| 10876 | install_special_sighandlers(); | 10894 | install_special_sighandlers(); |
| 10877 | #else | 10895 | #else |
