[ksh93-integration-discuss] ksh93 and |libc::wordexp()|, try 2 (and SMF debugging rants) ...

Roland Mainz roland.mainz at nrubsig.org
Tue Jun 6 18:20:29 PDT 2006


Hi!

----

Attached is a patch for B37 usr/src/lib/libc/ which switches
|libc::wordexp()| over to use ksh93 for it's tasks. The patch now works
with svc/inetd flawlessly (except that it spamms syslog() with debug
output from the patch and the WRDE_NOCMD mode via rksh doesn't work yet
(see
http://mail.opensolaris.org/pipermail/ksh93-integration-discuss/2006-June/000392.html
for a posible solution, right now the #ifdef'ed out part of the patch
does not work since calling "exec" for stdin/stdout/stderr redirection
is not allowed in "rksh" (="restricted") mode)).

Slightly offtopic (WARNING: Offensive language may be used below):
<rant>
I also like to COMPLAIN about the svc/SMF framework in Solaris. It made
services such as inetd a SERIOUS PAIN to debug. There is no longer an
effective way to insert a debugger in the chain like it was possible
with Solaris < 10 nor is it effectively possible to attach a debugger
later because something seems to prevent dbx/gdb from being able to
track the smf/inetd children. The whole situation seriously sucks and
yesterday (when I did the debugging) I was very close to wish that
someone gets fed to komodo dragons, alive and feet first (that he/she
can watch being eaten alive) ... xx@@@!!... ;-((
</rant>

----

Bye,
Roland

-- 
  __ .  . __
 (o.\ \/ /.o) roland.mainz at nrubsig.org
  \__\/\/__/  MPEG specialist, C&&JAVA&&Sun&&Unix programmer
  /O /==\ O\  TEL +49 641 7950090
 (;O/ \/ \O;)
-------------- next part --------------
Index: port/regex/wordexp.c
===================================================================
--- port/regex/wordexp.c	(revision 269)
+++ port/regex/wordexp.c	(working copy)
@@ -41,6 +41,7 @@
  * wordexp, wordfree -- POSIX.2 D11.2 word expansion routines.
  *
  * Copyright 1985, 1992 by Mortice Kern Systems Inc.  All rights reserved.
+ * Modified by Roland Mainz <roland.mainz at nrubsig.org> to support ksh93
  *
  */
 
@@ -57,14 +58,16 @@
 #include <wordexp.h>
 #include <stdio.h>
 #include <errno.h>
+#if 1
+#include <syslog.h>
+#endif
 
 #define	INITIAL	8		/* initial pathv allocation */
 #define	BUFSZ	256		/* allocation unit of the line buffer */
 
-static int	append(wordexp_t *, char *);
+/* Local prototypes */
+static int append(wordexp_t *, char *);
 
-extern	int __xpg4;	/* defined in _xpg4.c; 0 if not xpg4-compiled program */
-
 /*
  * Do word expansion.
  * We just pass our arguments to shell with -E option.  Note that the
@@ -74,25 +77,18 @@
 int
 wordexp(const char *word, wordexp_t *wp, int flags)
 {
-	static char options[9] = "-";
-	static char *args[4];
-	const char *path;
+	char *args[10];
 	wordexp_t wptmp;
 	size_t si;
 	int i;
 	pid_t pid;
-	char *line, *eob, *cp;		/* word from shell */
+	char *line, *eob, *cp;	/* word from shell */
 	int rv = WRDE_ERRNO;
 	int status;
-	int pv[2];			/* pipe from shell stdout */
-	FILE *fp;			/* pipe read stream */
-	char *optendp = options+1;
+	int pv[2];		/* pipe from shell stdout */
+	FILE *fp;		/* pipe read stream */
 	int serrno, tmpalloc;
-	char *wd = NULL;
 
-	static const char *sun_path = "/bin/ksh";
-	static const char *xpg4_path = "/usr/xpg4/bin/sh";
-
 	/*
 	 * Do absolute minimum neccessary for the REUSE flag. Eventually
 	 * want to be able to actually avoid excessive malloc calls.
@@ -138,34 +134,16 @@
 	}
 
 	/*
-	 * Turn flags into shell options
-	 */
-	*optendp++ = (char)0x05;		/* ksh -^E */
-	if (flags & WRDE_UNDEF)
-		*optendp++ = 'u';
-	if (flags & WRDE_NOCMD)
-		*optendp++ = 'N';
-	*optendp = '\0';
-
-	if (getenv("PWD") == NULL) {
-		if ((wd = malloc(PATH_MAX + 4)) == NULL)
-			goto cleanup;
-		(void) strcpy(wd, "PWD=");
-		if (getcwd(&wd[4], PATH_MAX) == NULL)
-			(void) strcpy(&wd[4], "/");
-	}
-
-	/*
 	 * Set up pipe from shell stdout to "fp" for us
 	 */
 	if (pipe(pv) < 0)
 		goto cleanup;
 
 	/*
-	 * Fork/exec shell with -E word
+	 * Fork/exec shell
 	 */
 
-	if ((pid = fork1()) == -1) {
+	if ((pid = fork()) == -1) {
 		serrno = errno;
 		(void) close(pv[0]);
 		(void) close(pv[1]);
@@ -173,32 +151,59 @@
 		goto cleanup;
 	}
 
-	if (pid == 0) { 	/* child */
-		if (wd != NULL) {
-			/*
-			 * fork1 handler takes care of __environ_lock.
-			 * Thus we can safely call putenv().
-			 */
-			(void) putenv(wd);
-		}
+	if (pid == 0) {	 /* child */
+		char buff[120+strlen(word)]; /* Needs C99 */
+		int i;
+		const char *path;
 
 		(void) dup2(pv[1], 1);
 		(void) close(pv[0]);
 		(void) close(pv[1]);
 
+		if (flags & WRDE_NOCMD) {
+			/*
+			 * Use restricted shell (rksh) here to put the word
+			 * expansion into a "cage" which prevents users
+			 * from executing external commands (outside those
+			 * listed by ${PATH}).
+			 */
+#if 0
+			path = "/usr/bin/rksh";
+#else
+			path = "/usr/bin/ksh93";
+#endif
+			putenv("PATH=/usr/lib/libc/libc_wordexp_commands");
+		}
+		else
+		{
+			path = "/usr/bin/ksh93";
+		}
+
+		i = 0;
+
+		buff[0] = '\0';
+		if (flags & WRDE_UNDEF)
+			strcat(buff, "set -o nounset ; ");
 		if ((flags & WRDE_SHOWERR) == 0) {
-			int devnull;
-			devnull = open("/dev/null", O_WRONLY);
-			(void) dup2(devnull, 2);
-			if (devnull != 2)
-				(void) close(devnull);
+			/*
+			 * The newline ('\n') is neccesary to make sure that
+			 * the redirection to /dev/null is already active in
+			 * the case the printf below contains a syntax
+			 * error...
+			 */
+			strcat(buff, "exec 2>/dev/null\n");
 		}
+		/* Squish stdin */
+		strcat(buff, "exec 0</dev/null\n");
+		sprintf(&buff[strlen(buff)], "print -f \"%%s\\000\" %s", word);
 
-		path = __xpg4 ? xpg4_path : sun_path;
-		args[0] = strrchr(path, '/') + 1;
-		args[1] = options;
-		args[2] = (char *)word;
-		args[3] = NULL;
+#if 1
+		syslog(LOG_CRIT, "wordexp(): cmd='%s', buffer='%s'", path, buff);
+#endif
+		args[i++] = strrchr(path, '/') + 1;
+		args[i++] = "-c";
+		args[i++] = buff;
+		args[i++] = NULL;
 
 		(void) execv(path, args);
 		_exit(127);
@@ -206,7 +211,7 @@
 
 	(void) close(pv[1]);
 
-	if ((fp = fdopen(pv[0], "rb")) == NULL) {
+	if ((fp = fdopen(pv[0], "r")) == NULL) {
 		serrno = errno;
 		(void) close(pv[0]);
 		errno = serrno;
@@ -268,8 +273,6 @@
 			wordfree(&wptmp);
 	}
 
-	if (wd)
-		free(wd);
 	/*
 	 * Map ksh errors to wordexp() errors
 	 */


More information about the ksh93-integration-discuss mailing list