[PATCH 1/3] lib: introduce ul_default_shell() for consistent shell resolution
Alessandro Ratti <[email protected]> Sun, 23 Nov 2025 16:32:44 +0100
| Newsgroups | org.kernel.vger.util-linux |
|---|---|
| Message-ID | <[email protected]> |
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 <[email protected]> Suggested-by: Thomas Weißschuh <[email protected]> Signed-off-by: Alessandro Ratti <[email protected]> --- include/shells.h | 6 ++++++ lib/Makemodule.am | 1 + lib/shells.c | 26 ++++++++++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/include/shells.h b/include/shells.h index c770a13ba..eca2b4187 100644 --- a/include/shells.h +++ b/include/shells.h @@ -4,7 +4,13 @@ #ifndef UTIL_LINUX_SHELLS_H #define UTIL_LINUX_SHELLS_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); +struct passwd; +const char *ul_default_shell(int flags, const struct passwd *pw); + #endif /* UTIL_LINUX_SHELLS_H */ diff --git a/lib/Makemodule.am b/lib/Makemodule.am index a9da57734..1d598faa2 100644 --- a/lib/Makemodule.am +++ b/lib/Makemodule.am @@ -49,6 +49,7 @@ libcommon_la_SOURCES = \ if LINUX libcommon_la_SOURCES += \ lib/linux_version.c \ + lib/shells.c \ lib/loopdev.c endif diff --git a/lib/shells.c b/lib/shells.c index 13f293c5e..ef2aecd0f 100644 --- a/lib/shells.c +++ b/lib/shells.c @@ -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; +} -- 2.51.1