From: Alessandro Ratti Date: Sun, 23 Nov 2025 15:24:52 +0000 (+0100) Subject: *: use ul_default_shell() for interactive shell spawning X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6651ae5822610789d9ca620c4e0e65c3bd4e12af;p=thirdparty%2Futil-linux.git *: use ul_default_shell() for interactive shell spawning Update tools that spawn interactive shells to use ul_default_shell() for consistent shell resolution. This ensures these tools respect both $SHELL and the user's configured shell from the passwd database before falling back to _PATH_BSHELL. Affected tools: - script(1): fixes history truncation when invoked without $SHELL - scriptlive(1): consistent with script(1) behavior - flock(1): for -c command execution - more(1): for shell escape feature - exec_shell (used by unshare(1) and nsenter(1)) This change addresses user reports of data loss due to tools defaulting to /bin/sh instead of the user's configured shell, particularly affecting command history with different HISTSIZE configurations. Addresses: https://github.com/util-linux/util-linux/issues/3865 Signed-off-by: Alessandro Ratti --- diff --git a/lib/exec_shell.c b/lib/exec_shell.c index ffe65f006..8f10ea4df 100644 --- a/lib/exec_shell.c +++ b/lib/exec_shell.c @@ -26,19 +26,15 @@ #include "xalloc.h" #include "exec_shell.h" - -#define DEFAULT_SHELL "/bin/sh" +#include "shells.h" void __attribute__((__noreturn__)) exec_shell(void) { - const char *shell = getenv("SHELL"); + const char *shell = ul_default_shell(0, NULL); char *shellc; const char *shell_basename; char *arg0; - if (!shell) - shell = DEFAULT_SHELL; - shellc = xstrdup(shell); shell_basename = basename(shellc); xasprintf(&arg0, "-%s", shell_basename); diff --git a/sys-utils/flock.c b/sys-utils/flock.c index 4cc0610e5..642e026c8 100644 --- a/sys-utils/flock.c +++ b/sys-utils/flock.c @@ -47,6 +47,7 @@ #include "closestream.h" #include "monotonic.h" #include "timer.h" +#include "shells.h" #ifndef F_OFD_GETLK #define F_OFD_GETLK 36 @@ -207,6 +208,7 @@ int main(int argc, char *argv[]) int conflict_exit_code = 1; char **cmd_argv = NULL, *sh_c_argv[4]; const char *filename = NULL; + enum { OPT_VERBOSE = CHAR_MAX + 1, OPT_FCNTL, @@ -327,9 +329,7 @@ int main(int argc, char *argv[]) _("%s requires exactly one command argument"), argv[optind + 1]); cmd_argv = sh_c_argv; - cmd_argv[0] = getenv("SHELL"); - if (!cmd_argv[0] || !*cmd_argv[0]) - cmd_argv[0] = _PATH_BSHELL; + cmd_argv[0] = (char *)ul_default_shell(0, NULL); cmd_argv[1] = "-c"; cmd_argv[2] = argv[optind + 2]; cmd_argv[3] = NULL; diff --git a/term-utils/script.c b/term-utils/script.c index ff7f4409f..4e302347f 100644 --- a/term-utils/script.c +++ b/term-utils/script.c @@ -70,6 +70,7 @@ #include "signames.h" #include "pty-session.h" #include "debug.h" +#include "shells.h" static UL_DEBUG_DEFINE_MASK(script); UL_DEBUG_DEFINE_MASKNAMES(script) = UL_DEBUG_EMPTY_MASKNAMES; @@ -966,9 +967,7 @@ int main(int argc, char **argv) log_associate(&ctl, &ctl.in, timingfile, format); } - shell = getenv("SHELL"); - if (!shell) - shell = _PATH_BSHELL; + shell = ul_default_shell(0, NULL); ctl.pty = ul_new_pty(ctl.isterm); if (!ctl.pty) diff --git a/term-utils/scriptlive.c b/term-utils/scriptlive.c index e4a3434ed..6ac685506 100644 --- a/term-utils/scriptlive.c +++ b/term-utils/scriptlive.c @@ -38,6 +38,7 @@ #include "pty-session.h" #include "script-playutils.h" #include "monotonic.h" +#include "shells.h" #define SCRIPT_MIN_DELAY 0.0001 /* from original scriptreplay.pl */ @@ -281,9 +282,7 @@ main(int argc, char *argv[]) replay_set_delay_max(ss.setup, &maxdelay); replay_set_delay_min(ss.setup, &mindelay); - shell = getenv("SHELL"); - if (shell == NULL) - shell = _PATH_BSHELL; + shell = ul_default_shell(0, NULL); fprintf(stdout, _(">>> scriptlive: Starting your typescript execution by %s.\n"), command ? command : shell); diff --git a/text-utils/more.c b/text-utils/more.c index 4980aef4c..bc04064cf 100644 --- a/text-utils/more.c +++ b/text-utils/more.c @@ -89,6 +89,7 @@ #include "widechar.h" #include "closestream.h" #include "env.h" +#include "shells.h" #ifdef TEST_PROGRAM # define NON_INTERACTIVE_MORE 1 @@ -174,7 +175,7 @@ struct more_control { int next_jump; /* number of lines to skip ahead */ char **file_names; /* The list of file names */ int num_files; /* Number of files left to process */ - char *shell; /* name of the shell to use */ + const char *shell; /* name of the shell to use */ int sigfd; /* signalfd() file descriptor */ sigset_t sigset; /* signal operations */ char *line_buf; /* line buffer */ @@ -2110,8 +2111,7 @@ static void initterm(struct more_control *ctl) if ((ctl->backspace_ch = tigetstr(TERM_BACKSPACE)) == NULL) ctl->backspace_ch = BACKSPACE; - if ((ctl->shell = getenv("SHELL")) == NULL) - ctl->shell = _PATH_BSHELL; + ctl->shell = ul_default_shell(0, NULL); } int main(int argc, char **argv)