ul_close_all_fds(STDERR_FILENO + 1, ~0U);
}
+static bool build_shell_argv(char *shell, char **child_argv)
+{
+ bool script;
+ int child_argc = 0;
+
+ /* if the shell field has a space: treat it like a shell script */
+ script = strchr(shell, ' ') != NULL;
+
+ if (script) {
+ char *buff;
+
+ xasprintf(&buff, "exec %s", shell);
+ child_argv[child_argc++] = "/bin/sh";
+ child_argv[child_argc++] = "-sh";
+ child_argv[child_argc++] = "-c";
+ child_argv[child_argc++] = buff;
+ } else {
+ char *buff, *p;
+
+ xasprintf(&buff, "-%.*s", PATH_MAX,
+ ((p = strrchr(shell, '/')) ?
+ p + 1 : shell));
+ child_argv[child_argc++] = shell;
+ child_argv[child_argc++] = buff;
+ }
+
+ child_argv[child_argc++] = NULL;
+
+ return script;
+}
+
+static void login_shell_fallback(char **child_argv)
+{
+#if defined (HAVE_LIBECONF) && defined (USE_VENDORDIR)
+ size_t size = 0;
+ econf_err error;
+ char **keys = NULL;
+ econf_file *key_file = open_etc_shells();
+
+ if (!key_file)
+ return;
+
+ error = econf_getKeys(key_file, NULL, &size, &keys);
+ if (error) {
+ econf_free(key_file);
+ errx(EXIT_FAILURE,
+ _("Cannot evaluate entries in shells files: %s"),
+ econf_errString(error));
+ }
+
+ for (size_t i = 0; i < size; i++) {
+ build_shell_argv(keys[i], child_argv);
+ execvp(child_argv[0], child_argv + 1);
+ }
+ econf_free(keys);
+ econf_free(key_file);
+#else
+ char *s;
+ setusershell();
+ while ((s = getusershell())) {
+ build_shell_argv(s, child_argv);
+ execvp(child_argv[0], child_argv + 1);
+ }
+ endusershell();
+#endif
+}
+
int main(int argc, char **argv)
{
char *child_argv[10];
- int child_argc = 0;
struct passwd *pwd;
struct login_context cxt = {
.tty_mode = TTY_MODE, /* tty chmod() */
printf(_("Logging in with home = \"/\".\n"));
}
- /* if the shell field has a space: treat it like a shell script */
- script = strchr(pwd->pw_shell, ' ') != NULL;
-
- if (script) {
- char *buff;
-
- xasprintf(&buff, "exec %s", pwd->pw_shell);
- child_argv[child_argc++] = "/bin/sh";
- child_argv[child_argc++] = "-sh";
- child_argv[child_argc++] = "-c";
- child_argv[child_argc++] = buff;
- } else {
- char *buff, *p;
-
- xasprintf(&buff, "-%.*s", PATH_MAX,
- ((p = strrchr(pwd->pw_shell, '/')) ?
- p + 1 : pwd->pw_shell));
- child_argv[child_argc++] = pwd->pw_shell;
- child_argv[child_argc++] = buff;
- }
-
- child_argv[child_argc++] = NULL;
-
/* http://www.linux-pam.org/Linux-PAM-html/adg-interface-by-app-expected.html#adg-pam_end */
(void) pam_end(cxt.pamh, PAM_SUCCESS|PAM_DATA_SILENT);
+ script = build_shell_argv(pwd->pw_shell, child_argv);
execvp(child_argv[0], child_argv + 1);
- if (script)
- warn(_("couldn't exec shell script"));
- else
- warn(_("no shell"));
+ if (getlogindefs_bool("LOGIN_SHELL_FALLBACK", 0)) {
+ login_shell_fallback(child_argv);
+ warn(_("no available shell"));
+ } else {
+ if (script)
+ warn(_("couldn't exec shell script"));
+ else
+ warn(_("no shell"));
+ }
exit(EXIT_SUCCESS);
}