diff --git a/ChangeLog b/ChangeLog index ec2ffd66..aafef322 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-07-20 Nicolas François + + * NEWS, src/su.c, libmisc/shell.c: Added support for shells being a + shell script without a shebang. + 2009-07-19 Jean-Louis Dupond * po/nl.po: Fix obvious mistake in Dutch translation. diff --git a/NEWS b/NEWS index f489dd40..7113390f 100644 --- a/NEWS +++ b/NEWS @@ -12,9 +12,12 @@ shadow-4.1.4.1 -> shadow-4.1.4.2 UNRELEASED reverse order, accounts are packed close to SYS_?ID_MAX if SYS_?ID_MIN is already used but there are still dome gaps. +- login + * Add support for shells being a shell script without a shebang. - su * Preserve the DISPLAY and XAUTHORITY environment variables. This was only the case in the non PAM enabled versions. + * Add support for shells being a shell script without a shebang. *** translation * The Finnish translation of passwd(1) was outdated and is no more diff --git a/libmisc/shell.c b/libmisc/shell.c index e3d8931e..2dd3bb25 100644 --- a/libmisc/shell.c +++ b/libmisc/shell.c @@ -2,6 +2,7 @@ * Copyright (c) 1989 - 1991, Julianne Frances Haugh * Copyright (c) 1996 - 1998, Marek Michałkiewicz * Copyright (c) 2003 - 2006, Tomasz Kłoczko + * Copyright (c) 2009 , Nicolas François * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -79,6 +80,15 @@ int shell (const char *file, /*@null@*/const char *arg, char *const envp[]) execle (file, arg, (char *) 0, envp); err = errno; + if (access (file, R_OK|X_OK) == 0) { + /* + * Assume this is a shell script (with no shebang). + * Interpret it with /bin/sh + */ + execle ("/bin/sh", "sh", file, (char *)0, envp); + err = errno; + } + /* * Obviously something is really wrong - I can't figure out * how to execute this stupid shell, so I might as well give diff --git a/src/su.c b/src/su.c index 876b4605..3e87425e 100644 --- a/src/su.c +++ b/src/su.c @@ -2,7 +2,7 @@ * Copyright (c) 1989 - 1994, Julianne Frances Haugh * Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 2000 - 2006, Tomasz Kłoczko - * Copyright (c) 2007 - 2008, Nicolas François + * Copyright (c) 2007 - 2009, Nicolas François * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -174,6 +174,40 @@ static void su_failure (const char *tty) exit (1); } +/* + * execve_shell - Execute a shell with execve, or interpret it with + * /bin/sh + */ +void execve_shell (const char *shellstr, char *args[], char *const envp[]) +{ + int err; + (void) execve (shellstr, (char **) args, envp); + err = errno; + + if (access (shellstr, R_OK|X_OK) == 0) { + /* + * Assume this is a shell script (with no shebang). + * Interpret it with /bin/sh + */ + size_t n_args = 0; + char **targs; + while (NULL != args[n_args]) { + n_args++; + } + targs = (char **) xmalloc ((n_args + 2) * sizeof (args[0])); + targs[0] = "sh"; + targs[1] = xstrdup (shellstr); + targs[n_args+1] = NULL; + while (1 != n_args) { + targs[n_args] = args[n_args - 1]; + n_args--; + } + + (void) execve ("/bin/sh", targs, envp); + } else { + errno = err; + } +} #ifdef USE_PAM /* Signal handler for parent process later */ @@ -206,8 +240,9 @@ static void run_shell (const char *shellstr, char *args[], bool doshell, if (doshell) { (void) shell (shellstr, (char *) args[0], envp); } else { - (void) execve (shellstr, (char **) args, envp); + execve_shell (shellstr, (char **) args, envp); } + exit (errno == ENOENT ? E_CMD_NOTFOUND : E_CMD_NOEXEC); } else if ((pid_t)-1 == child) { (void) fprintf (stderr, "%s: Cannot fork user shell\n", Prog); @@ -315,7 +350,7 @@ static void usage (void) */ int main (int argc, char **argv) { - char *cp; + const char *cp; const char *tty = NULL; /* Name of tty SU is run from */ bool doshell = false; bool fakelogin = false; @@ -949,7 +984,7 @@ int main (int argc, char **argv) */ argv[-1] = shellstr; #ifndef USE_PAM - (void) execve (shellstr, &argv[-1], environ); + execve_shell (shellstr, &argv[-1], environ); err = errno; (void) fputs (_("No shell\n"), stderr); SYSLOG ((LOG_WARN, "Cannot execute %s", shellstr));