aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2025-08-03 17:37:32 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2025-08-03 17:37:32 +0200
commit58a54fbd5a48a96036cecd07ba54ff37518af373 (patch)
treec2f902f30ab888fa2fdf0e27f758a33bd65907b7 /shell
parent778fce3e7089c9546fe3f147d355a008f5e12c42 (diff)
downloadbusybox-w32-58a54fbd5a48a96036cecd07ba54ff37518af373.tar.gz
busybox-w32-58a54fbd5a48a96036cecd07ba54ff37518af373.tar.bz2
busybox-w32-58a54fbd5a48a96036cecd07ba54ff37518af373.zip
hush: disentangle interactiveness/job_control setup code
...and discover that we can do away with 1-3 initialization syscalls. function old new delta hush_main 1152 1146 -6 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r--shell/hush.c146
1 files changed, 67 insertions, 79 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 98812b507..debae4d58 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -10790,100 +10790,86 @@ int hush_main(int argc, char **argv)
10790 10790
10791 /* A shell is interactive if the '-i' flag was given, 10791 /* A shell is interactive if the '-i' flag was given,
10792 * or if all of the following conditions are met: 10792 * or if all of the following conditions are met:
10793 * no -c command 10793 * not -c 'CMD'
10794 * no arguments remaining or the -s flag given 10794 * not running a script (no arguments remaining, or -s flag given)
10795 * standard input is a terminal 10795 * standard input is a terminal
10796 * standard output is a terminal 10796 * standard output is a terminal
10797 * Refer to Posix.2, the description of the 'sh' utility. 10797 * Refer to Posix.2, the description of the 'sh' utility.
10798 */ 10798 */
10799#if ENABLE_HUSH_JOB 10799#if ENABLE_HUSH_INTERACTIVE
10800 if (!G_reexeced_on_NOMMU
10801 && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)
10802 ) {
10803 G_saved_tty_pgrp = tcgetpgrp(STDIN_FILENO);
10804 debug_printf("saved_tty_pgrp:%d\n", G_saved_tty_pgrp);
10805 if (G_saved_tty_pgrp < 0)
10806 G_saved_tty_pgrp = 0;
10807
10808 /* try to dup stdin to high fd#, >= 255 */
10809 G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254);
10810 if (G_interactive_fd < 0) {
10811 /* try to dup to any fd */
10812 G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, -1);
10813 if (G_interactive_fd < 0) {
10814 /* give up */
10815 G_interactive_fd = 0;
10816 G_saved_tty_pgrp = 0;
10817 }
10818 }
10819 }
10820 debug_printf("interactive_fd:%d\n", G_interactive_fd);
10821 if (G_interactive_fd) {
10822 if (G_saved_tty_pgrp) {
10823 /* If we were run as 'hush &', sleep until we are
10824 * in the foreground (tty pgrp == our pgrp).
10825 * If we get started under a job aware app (like bash),
10826 * make sure we are now in charge so we don't fight over
10827 * who gets the foreground */
10828 while (1) {
10829 pid_t shell_pgrp = getpgrp();
10830 G_saved_tty_pgrp = tcgetpgrp(G_interactive_fd);
10831 if (G_saved_tty_pgrp == shell_pgrp)
10832 break;
10833 /* send TTIN to ourself (should stop us) */
10834 kill(- shell_pgrp, SIGTTIN);
10835 }
10836 }
10837
10838 /* Install more signal handlers */
10839 install_special_sighandlers();
10840
10841 if (G_saved_tty_pgrp) {
10842 /* Set fatal signals to restore saved_tty_pgrp */
10843 install_fatal_sighandlers();
10844 /* Put ourselves in our own process group
10845 * (bash, too, does this only if ctty is available) */
10846 bb_setpgrp(); /* is the same as setpgid(our_pid, our_pid); */
10847 /* Grab control of the terminal */
10848 tcsetpgrp(G_interactive_fd, G.root_pid);
10849 }
10850 init_line_editing();
10851 }
10852#elif ENABLE_HUSH_INTERACTIVE
10853 /* No job control compiled in, only prompt/line editing */
10854 if (!G_reexeced_on_NOMMU 10800 if (!G_reexeced_on_NOMMU
10855 && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) 10801 && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)
10856 ) { 10802 ) {
10803 /* Try to dup stdin to high fd#, >= 255 */
10857 G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254); 10804 G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254);
10858 if (G_interactive_fd < 0) { 10805 if (G_interactive_fd < 0) {
10859 /* try to dup to any fd */ 10806 /* Try to dup to any fd */
10860 G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, -1); 10807 G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, -1);
10861 if (G_interactive_fd < 0) 10808 if (G_interactive_fd < 0)
10862 /* give up */ 10809 /* Give up */
10863 G_interactive_fd = 0; 10810 G_interactive_fd = 0;
10864 } 10811 }
10812 debug_printf("interactive_fd:%d\n", G_interactive_fd);
10865 if (G_interactive_fd) { 10813 if (G_interactive_fd) {
10814// TODO? bash:
10815// if interactive but not a login shell, sources ~/.bashrc
10816// (--norc turns this off, --rcfile <file> overrides)
10817# if ENABLE_HUSH_JOB
10818 /* Can we do job control? */
10819 G_saved_tty_pgrp = tcgetpgrp(G_interactive_fd);
10820 debug_printf("saved_tty_pgrp:%d\n", G_saved_tty_pgrp);
10821 if (G_saved_tty_pgrp < 0)
10822 G_saved_tty_pgrp = 0; /* no */
10823 if (G_saved_tty_pgrp) {
10824 /* If we were run as 'hush &', sleep until we are
10825 * in the foreground (tty pgrp == our pgrp).
10826 * If we get started under a job aware app (like bash),
10827 * make sure we are now in charge so we don't fight over
10828 * who gets the foreground */
10829 while (1) {
10830 pid_t shell_pgrp = getpgrp();
10831 if (G_saved_tty_pgrp == shell_pgrp) {
10832/* Often both pgrps here are set to our pid - but not always!
10833 * Example: sh -c 'echo $$; hush; echo FIN'
10834 * Here, the parent shell is not interactive, so it does NOT set up
10835 * a separate process group for its children, and we (hush) initinally
10836 * run in parent's process group (until we set up our own a few lines down).
10837 */
10838 //bb_error_msg("process groups tty:%d hush:%d", G_saved_tty_pgrp, shell_pgrp);
10839 break;
10840 }
10841 /* Send TTIN to ourself (should stop us) */
10842 kill(- shell_pgrp, SIGTTIN);
10843 G_saved_tty_pgrp = tcgetpgrp(G_interactive_fd);
10844 }
10845 }
10846# endif
10847 /* Install more signal handlers */
10866 install_special_sighandlers(); 10848 install_special_sighandlers();
10849# if ENABLE_HUSH_JOB
10850 if (G_saved_tty_pgrp) {
10851 /* Set fatal signals to restore saved_tty_pgrp */
10852 install_fatal_sighandlers();
10853 /* (The if() is an optimization: can avoid two redundant syscalls) */
10854 if (G_saved_tty_pgrp != G.root_pid) {
10855 /* Put ourselves in our own process group
10856 * (bash, too, does this only if ctty is available) */
10857 bb_setpgrp(); /* is the same as setpgid(our_pid, our_pid); */
10858 /* Grab control of the terminal */
10859 tcsetpgrp(G_interactive_fd, G.root_pid);
10860 }
10861 }
10862# endif
10863# if ENABLE_FEATURE_EDITING_FANCY_PROMPT
10864 /* Set (but not export) PS1/2 unless already set */
10865 if (!get_local_var_value("PS1"))
10866 set_local_var_from_halves("PS1", "\\w \\$ ");
10867 if (!get_local_var_value("PS2"))
10868 set_local_var_from_halves("PS2", "> ");
10869# endif
10867 init_line_editing(); 10870 init_line_editing();
10868 }
10869 }
10870#else
10871 /* We have interactiveness code disabled */
10872#endif
10873 /* bash:
10874 * if interactive but not a login shell, sources ~/.bashrc
10875 * (--norc turns this off, --rcfile <file> overrides)
10876 */
10877 10871
10878 if (G_interactive_fd) { 10872# if !ENABLE_FEATURE_SH_EXTRA_QUIET
10879#if ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT
10880 /* Set (but not export) PS1/2 unless already set */
10881 if (!get_local_var_value("PS1"))
10882 set_local_var_from_halves("PS1", "\\w \\$ ");
10883 if (!get_local_var_value("PS2"))
10884 set_local_var_from_halves("PS2", "> ");
10885#endif
10886 if (!ENABLE_FEATURE_SH_EXTRA_QUIET) {
10887 /* note: ash and hush share this string */ 10873 /* note: ash and hush share this string */
10888 printf("\n\n%s %s\n" 10874 printf("\n\n%s %s\n"
10889 IF_HUSH_HELP("Enter 'help' for a list of built-in commands.\n") 10875 IF_HUSH_HELP("Enter 'help' for a list of built-in commands.\n")
@@ -10891,8 +10877,10 @@ int hush_main(int argc, char **argv)
10891 bb_banner, 10877 bb_banner,
10892 "hush - the humble shell" 10878 "hush - the humble shell"
10893 ); 10879 );
10894 } 10880# endif
10895 } 10881 } /* if become interactive */
10882 } /* if on tty */
10883#endif /* if INTERACTIVE is allowed by build config */
10896 10884
10897 parse_and_run_file(hfopen(NULL)); /* stdin */ 10885 parse_and_run_file(hfopen(NULL)); /* stdin */
10898 10886