tags 479406 pending
thanks

Hi,

On Sun, Jul 19, 2009 at 08:58:49PM +0100, stephane_chaze...@yahoo.fr wrote:
> 2009-07-18 21:26:56 +0200, Nicolas François:
> > Ping
> 
> Sorry, forgot to reply to your earlier email.

No problem (it took me a year for the previous answer ;)

> > > Are there other su / login implementations which behave that way?
> [...]
> 
> AFAICS, the "login" from util-linux (derived from BSD) and the
> one from NetBSD and OpenBSD at least do use the exec?p variants
> (from a quick look at there source code).
> 
> The OpenSolaris one seems to be checking for that case (pw_shell
> being a shell script) explicitely and treats it specially:
> 
> http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/login/login.c#2507

login is the easiest, su is more complex because the behavior of
"su -c <command>" must be defined in this case. So I will just make it as
"/bin/sh <shell> -c <command>"

I will commit and test the attached patch, which should fix it for both
login and su.

Best Regards,
-- 
Nekral
Index: libmisc/shell.c
===================================================================
--- libmisc/shell.c	(révision 3031)
+++ libmisc/shell.c	(copie de travail)
@@ -79,6 +80,15 @@
 	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: src/su.c
===================================================================
--- src/su.c	(révision 3031)
+++ src/su.c	(copie de travail)
@@ -174,7 +174,41 @@
 	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 */
 static void catch_signals (unused int sig)
@@ -206,8 +240,9 @@
 		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);
@@ -949,7 +984,7 @@
 		 */
 		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));

Reply via email to