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>
#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 */
if LINUX
libcommon_la_SOURCES += \
lib/linux_version.c \
+ lib/shells.c \
lib/loopdev.c
endif
randutils.c
sha1.c
sha256.c
+ shells.c
signames.c
strutils.c
strv.c
/*
* 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>
#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;
+}