]> granicus.if.org Git - shadow/commitdiff
* NEWS, src/su.c, libmisc/shell.c: Added support for shells being a
authornekral-guest <nekral-guest@5a98b0ae-9ef6-0310-add3-de5d479b70d7>
Mon, 20 Jul 2009 14:00:50 +0000 (14:00 +0000)
committernekral-guest <nekral-guest@5a98b0ae-9ef6-0310-add3-de5d479b70d7>
Mon, 20 Jul 2009 14:00:50 +0000 (14:00 +0000)
shell script without a shebang.

ChangeLog
NEWS
libmisc/shell.c
src/su.c

index ec2ffd66bcf9934c694998a7e12ec0d141f6227f..aafef32295afaf881c931e307d5be820c5265c0b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2009-07-20  Nicolas François  <nicolas.francois@centraliens.net>
+
+       * NEWS, src/su.c, libmisc/shell.c: Added support for shells being a
+       shell script without a shebang.
+
 2009-07-19  Jean-Louis Dupond  <info@dupondje.be>
 
        * po/nl.po: Fix obvious mistake in Dutch translation.
diff --git a/NEWS b/NEWS
index f489dd403f294c50124ee151ba157ce0cd5d13cd..7113390fbee52317d9b1dd321af7b9ca7adfb37d 100644 (file)
--- 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
index e3d8931e95fc3478ebfefcc7ccddb7387f7f184c..2dd3bb25aba6dbaf853882d85b31e99b84344a2f 100644 (file)
@@ -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
index 876b46051576e360e843da5f4b022641f04fc017..3e87425e72eeb8f06ac328ba37f6d789260c6415 100644 (file)
--- 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));