]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lib: introduce ul_default_shell() for consistent shell resolution
authorAlessandro Ratti <alessandro@0x65c.net>
Sun, 23 Nov 2025 15:20:57 +0000 (16:20 +0100)
committerAlessandro Ratti <alessandro@0x65c.net>
Mon, 1 Dec 2025 17:58:02 +0000 (18:58 +0100)
Add a new ul_default_shell() function to provide consistent shell
resolution across util-linux tools. The function follows a priority
order: $SHELL environment variable, user's shell from passwd database,
and finally _PATH_BSHELL as fallback.

The function supports flags to control its behavior:
- UL_SHELL_NOENV: skip $SHELL environment variable check
- UL_SHELL_NOPWD: skip passwd database lookup

This addresses the issue where tools like script(1) would default to
/bin/sh without respecting the user's configured shell, potentially
causing data loss.

Addresses: https://github.com/util-linux/util-linux/issues/3865
Suggested-by: Karel Zak <kzak@redhat.com>
Suggested-by: Thomas Weißschuh <thomas@t-8ch.de>
Signed-off-by: Alessandro Ratti <alessandro@0x65c.net>
include/shells.h
lib/Makemodule.am
lib/meson.build
lib/shells.c

index c770a13ba980597329f7890816b6b5449014a568..7f2d2469c2783d22630d8727fb9b857ee4c692ac 100644 (file)
@@ -4,7 +4,14 @@
 #ifndef UTIL_LINUX_SHELLS_H
 #define UTIL_LINUX_SHELLS_H
 
+#include <pwd.h>
+
+#define UL_SHELL_NOENV  (1 << 0)
+#define UL_SHELL_NOPWD  (1 << 1)
+
 extern void print_shells(FILE *out, const char *format);
 extern int is_known_shell(const char *shell_name);
 
+const char *ul_default_shell(int flags, const struct passwd *pw);
+
 #endif /* UTIL_LINUX_SHELLS_H */
index a9da577348baf8bb31bb81444cdf07b63123bd9e..1d598faa28414a5d0c49a58bc2fe376be6b15723 100644 (file)
@@ -49,6 +49,7 @@ libcommon_la_SOURCES = \
 if LINUX
 libcommon_la_SOURCES += \
        lib/linux_version.c \
+       lib/shells.c \
        lib/loopdev.c
 endif
 
index 0f94a9b99b3613a3ddbe205e515f968ae93db2b8..cb35ecbd60f4be3831ca38e6d9146d35349c24b4 100644 (file)
@@ -25,6 +25,7 @@ lib_common_sources = '''
        randutils.c
        sha1.c
        sha256.c
+       shells.c
        signames.c
        strutils.c
        strv.c
index 13f293c5e0c5e822296024f9035521822c8e3071..ef2aecd0f5ee5ad6153b1590e5413a6daa2fcd24 100644 (file)
@@ -1,6 +1,11 @@
 /*
  * SPDX-License-Identifier: GPL-2.0-or-later
  */
+#include <sys/types.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <paths.h>
+#include <unistd.h>
 #include <sys/syslog.h>
 #if defined (HAVE_LIBECONF) && defined (USE_VENDORDIR)
 #include <libeconf.h>
@@ -116,3 +121,24 @@ extern int is_known_shell(const char *shell_name)
 #endif
        return ret;
 }
+
+const char *ul_default_shell(int flags, const struct passwd *pw)
+{
+       const char *shell = NULL;
+
+       if (!(flags & UL_SHELL_NOENV)) {
+               shell = getenv("SHELL");
+               if (shell && *shell)
+                       return shell;
+       }
+       if (!(flags & UL_SHELL_NOPWD)) {
+               if (!pw)
+                       pw = getpwuid(getuid());
+               if (pw)
+                       shell = pw->pw_shell;
+               if (shell && *shell)
+                       return shell;
+       }
+
+       return _PATH_BSHELL;
+}