]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
*: use ul_default_shell() for interactive shell spawning
authorAlessandro Ratti <alessandro@0x65c.net>
Sun, 23 Nov 2025 15:24:52 +0000 (16:24 +0100)
committerAlessandro Ratti <alessandro@0x65c.net>
Mon, 1 Dec 2025 17:58:02 +0000 (18:58 +0100)
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 <alessandro@0x65c.net>
lib/exec_shell.c
sys-utils/flock.c
term-utils/script.c
term-utils/scriptlive.c
text-utils/more.c

index ffe65f006e82bb988af4eae534b79569fae6607a..8f10ea4df4933b55b331305c6ddb25675c778df8 100644 (file)
 #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);
index 4cc0610e501d3ed054d42b3953eac48aeb1ac99b..642e026c855b17b2fcbc93af6a69c718ac277b3a 100644 (file)
@@ -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;
index ff7f4409f61fdeccaed453e818eac2f47341a8cd..4e302347f22b0646f73b828f14b8aa1bafa431d0 100644 (file)
@@ -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)
index e4a3434ed5bd410201f19b272a71a5b6b6b416d9..6ac685506f208c490630d89bae69754634e602f6 100644 (file)
@@ -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);
index 4980aef4cac10063d8de02b927a488a9c4289a09..bc04064cf15151b7d2d20be821766a95cd30ff57 100644 (file)
@@ -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)