aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2025-08-03 01:02:55 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2025-08-03 01:26:25 +0200
commitcdbb6957f1bfafbcbe7e9abbb79979c8cd29881c (patch)
tree5c68d0f57b5466f12f26900001dd034202594684 /shell
parente591316e020258d07dc987c5f2f4b7a03d786ddd (diff)
downloadbusybox-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.c126
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);
2105static void save_history_run_exit_trap_and_exit(int exitcode) 2111static 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
10230static 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
10221static void install_sighandlers(unsigned mask) 10276static 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)
10356int hush_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 10411int hush_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
10357int hush_main(int argc, char **argv) 10412int 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