Index: branches/libc-0.6/src/emx/include/InnoTekLIBC/backend.h
===================================================================
--- branches/libc-0.6/src/emx/include/InnoTekLIBC/backend.h	(revision 3855)
+++ branches/libc-0.6/src/emx/include/InnoTekLIBC/backend.h	(revision 3859)
@@ -1042,4 +1042,20 @@
 /** When this flag is set, the exec / spawn backend will handle PC batch scripts. */
 extern int __libc_Back_gfProcessHandlePCBatchScripts;
+
+/**
+ * Gets the default shell for functions like system() and popen().
+ *
+ * @returns 0 on success, negative error number on failure.
+ * @param   pszShell        Where to put the path to the shell.
+ * @param   cbShell         The size of the buffer @a pszShell points to.
+ * @param   poffShellArg    Where to return the offset into @a pszShell of the
+ *                          first argument.  The system() and popen() calls has
+ *                          traditionally not included the path to /bin/sh.
+ * @param   pszCmdLineOpt   Where to put the shell option for specifying a
+ *                          command line it should execute.
+ * @param   cbCmdLineOpt    The size of the buffer @a pszCmdLineOpt points to.
+ */
+int __libc_Back_processGetDefaultShell(char *pszShell, size_t cbShell, size_t *poffShellArg,
+                                       char *pszCmdLineOpt, size_t cbCmdLineOpt);
 
 /** @} */
Index: branches/libc-0.6/src/emx/src/lib/io/popen.c
===================================================================
--- branches/libc-0.6/src/emx/src/lib/io/popen.c	(revision 3855)
+++ branches/libc-0.6/src/emx/src/lib/io/popen.c	(revision 3859)
@@ -10,4 +10,5 @@
 #include <fcntl.h>
 #include <errno.h>
+#include <InnotekLIBC/backend.h>
 
 static void restore (int org_handle, int org_private, int handle)
@@ -27,5 +28,8 @@
   int i, org_handle, org_private;
   FILE *f;
-  const char *sh, *base, *opt;
+  char szShell[260];
+  size_t offShellArg;
+  char szCmdLineOpt[8];
+  int rc;
 
   fcntl (pipe_local, F_SETFD, FD_CLOEXEC);
@@ -56,20 +60,13 @@
       return NULL;
     }
-  sh = getenv ("EMXSHELL");
-  if (sh == NULL)
-    sh = getenv ("COMSPEC");
-  if (sh == NULL)
+  rc = __libc_Back_processGetDefaultShell (&szShell[0], sizeof(szShell), &offShellArg, &szCmdLineOpt[0], sizeof(szCmdLineOpt));
+  if (rc != 0)
     {
       fclose (f);
       restore (org_handle, org_private, handle);
-      errno = ENOENT;
+      errno = -rc;
       return NULL;
     }
-  base = _getname (sh);
-  if (stricmp (base, "cmd.exe") == 0 || stricmp (base, "4os2.exe") == 0)
-    opt = "/c";
-  else
-    opt = "-c";
-  i = spawnlp (P_NOWAIT, sh, sh, opt, command, (char *)0);
+  i = spawnlp (P_NOWAIT, szShell, &szShell[offShellArg], szCmdLineOpt, command, (char *)0);
   if (i == -1)
     {
Index: branches/libc-0.6/src/emx/src/lib/libc.def
===================================================================
--- branches/libc-0.6/src/emx/src/lib/libc.def	(revision 3855)
+++ branches/libc-0.6/src/emx/src/lib/libc.def	(revision 3859)
@@ -1966,3 +1966,4 @@
     "___libc_Back_fsFileOwnerSetFH" @1962
     "___libc_Back_fsSymlinkOwnerSet" @1963
-
+    "___libc_Back_processGetDefaultShell" @1964
+    
Index: branches/libc-0.6/src/emx/src/lib/process/system.c
===================================================================
--- branches/libc-0.6/src/emx/src/lib/process/system.c	(revision 3855)
+++ branches/libc-0.6/src/emx/src/lib/process/system.c	(revision 3859)
@@ -1,52 +1,49 @@
-/* system.c (emx+gcc) -- Copyright (c) 1990-1995 by Eberhard Mattes */
+/* $Id: b_processSetResourceLimit.c 3770 2012-03-15 20:02:46Z bird $ */
+/** @file
+ * kNIX - get default shell for system() and popen().
+ *
+ * @copyright   Copyright (C) 2014 knut st. osmundsen <bird-klibc-spam-xiv@anduin.net>
+ * @licenses    MIT, BSD2, BSD3, BSD4, LGPLv2.1, LGPLv3.
+ */
 
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#define __LIBC_LOG_GROUP __LIBC_LOG_GRP_PROCESS
 #include "libc-alias.h"
 #include <stdlib.h>
-#include <string.h>
-#include <process.h>
+
 #include <io.h>
 #include <errno.h>
-#define __LIBC_LOG_GROUP __LIBC_LOG_GRP_PROCESS
-#include <InnoTekLIBC/logstrict.h>
+#include <process.h>
+#include <unistd.h>
+#include <InnotekLIBC/backend.h>
+#include <InnotekLIBC/logstrict.h>
 
-int _STD(system)(const char *name)
+
+int _STD(system)(const char *pszCmdLine)
 {
-    LIBCLOG_ENTER("name=%s\n", name);
-    int rc;
-    const char *sh, *base, *opt;
-
-    sh = getenv("EMXSHELL");
-    if (sh == NULL)
-        sh = getenv("COMSPEC");
-    if (sh == NULL)
-        sh = getenv("OS2_SHELL");
-    if (sh == NULL)
-        sh = getenv("SHELL");
-    if (sh == NULL)
+    LIBCLOG_ENTER("pszCmdLine=%s\n", pszCmdLine);
+    char szCmdLineOpt[8];
+    char szShell[260];
+    size_t offShellArg;
+    int rc = __libc_Back_processGetDefaultShell(szShell, sizeof(szShell), &offShellArg, szCmdLineOpt, sizeof(szCmdLineOpt));
+    if (rc == 0)
     {
-        errno = ENOENT;
-        LIBCLOG_ERROR_RETURN(-1, "ret -1 - no shell\n");
+        LIBCLOG_MSG("using shell: %s\n", pszCmdLine);
+        if (pszCmdLine == 0)
+            rc = access(szShell, F_OK) == 0;
+        else if (*pszCmdLine)
+            rc = spawnlp(P_WAIT, szShell, &szShell[offShellArg], (void *)NULL);
+        else
+            rc = spawnlp(P_WAIT, szShell, &szShell[offShellArg], szCmdLineOpt, pszCmdLine, (void *)NULL);
     }
-    LIBCLOG_MSG("using shell: %s\n", sh);
-    if (name == NULL)   /* Check for command interpreter */
-    {
-        LIBCLOG_MSG("check shell access\n");
-        rc = access(sh, 0) == 0;
-        LIBCLOG_RETURN_INT(rc);
-    }
-    if (*name == 0)
-        rc = spawnlp(P_WAIT, sh, sh, (char *)0);
     else
     {
-        base = _getname(sh);
-        if (    stricmp(base, "cmd.exe") == 0
-            ||  stricmp(base, "4os2.exe") == 0
-            ||  stricmp(base, "command.com") == 0
-            ||  stricmp(base, "4dos.com") == 0)
-            opt = "/c";
-        else
-            opt = "-c";
-        rc = spawnlp(P_WAIT, sh, sh, opt, name, (char *)0);
+        errno = -rc;
+        rc = -1;
     }
     LIBCLOG_RETURN_INT(rc);
 }
+
Index: branches/libc-0.6/src/emx/src/lib/sys/b_processGetDefaultShell.c
===================================================================
--- branches/libc-0.6/src/emx/src/lib/sys/b_processGetDefaultShell.c	(revision 3859)
+++ branches/libc-0.6/src/emx/src/lib/sys/b_processGetDefaultShell.c	(revision 3859)
@@ -0,0 +1,150 @@
+/* $Id$ */
+/** @file
+ * kNIX - get default shell for system() and popen().
+ *
+ * @copyright   Copyright (C) 2014 knut st. osmundsen <bird-klibc-spam-xiv@anduin.net>
+ * @licenses    MIT, BSD2, BSD3, BSD4, LGPLv2.1, LGPLv3.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "libc-alias.h"
+#include "syscalls.h"
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_PROCESS
+#include <InnotekLIBC/logstrict.h>
+#include <InnotekLIBC/libc.h>
+#include <InnotekLIBC/backend.h>
+
+
+/**
+ * Gets the default shell for functions like system() and popen().
+ *
+ * @returns 0 on success, negative error number on failure.
+ * @param   pszShell        Where to put the path to the shell.
+ * @param   cbShell         The size of the buffer @a pszShell points to.
+ * @param   poffShellArg    Where to return the offset into @a pszShell of the
+ *                          first argument.  The system() and popen() calls has
+ *                          traditionally not included the path to /bin/sh.
+ * @param   pszCmdLineOpt   Where to put the shell option for specifying a
+ *                          command line it should execute.
+ * @param   cbCmdLineOpt    The size of the buffer @a pszCmdLineOpt points to.
+ */
+int __libc_Back_processGetDefaultShell(char *pszShell, size_t cbShell, size_t *poffShellArg,
+                                       char *pszCmdLineOpt, size_t cbCmdLineOpt)
+{
+    const char *pszBase;
+    const char *pszEnv;
+    size_t cchEnv;
+    int fIsUnixShell = -1;
+
+    /*
+     * If the process isn't a no-unix process, try look for a shell under
+     * the unixroot.
+     */
+    if (!__libc_gfNoUnix)
+    {
+        struct stat st;
+        fIsUnixShell = 1;
+        pszEnv = "/@unixroot/bin/sh.exe";
+        if (stat(pszEnv, &st) != 0)
+        {
+            pszEnv = NULL;
+            if (stat("/@unixroot/bin/", &st) == 0)
+            {
+                pszEnv = "/@unixroot/bin/ash.exe";
+                if (stat(pszEnv, &st) < 0)
+                {
+                    pszEnv = "/@unixroot/bin/bash.exe";
+                    if (stat(pszEnv, &st) < 0)
+                    {
+                        fIsUnixShell = -1;
+                        pszEnv = NULL;
+                    }
+                }
+            }
+        }
+    }
+    else
+        pszEnv = NULL;
+
+    /*
+     * Fall back on various environment variables.
+     */
+    if (!pszEnv)
+    {
+        pszEnv = getenv("EMXSHELL");
+        if (!pszEnv)
+        {
+            pszEnv = getenv(!__libc_gfNoUnix ? "SHELL" : "COMSPEC");
+            if (!pszEnv)
+            {
+                pszEnv = getenv(!__libc_gfNoUnix ? "COMSPEC" : "SHELL");
+#ifdef __OS2__
+                if (!pszEnv)
+                    pszEnv = getenv("OS2_SHELL");
+#endif
+                if (!pszEnv)
+                    return -ENOENT;
+            }
+        }
+    }
+
+    /*
+     * Copy out the path.
+     */
+    cchEnv = strlen(pszEnv);
+    if (cchEnv >= cbShell)
+        return -ENAMETOOLONG;
+    memcpy(pszShell, pszEnv, cchEnv);
+    pszShell[cchEnv] = '\0';
+
+    if (cbCmdLineOpt < sizeof("-c"))
+        return -EOVERFLOW;
+
+    /*
+     * What kind of option does it take before a command line?
+     */
+    pszBase = _getname(pszShell);
+    if (   !stricmp(pszBase, "cmd.exe")
+#ifdef __OS2__
+        || !stricmp(pszBase, "4os2.exe")
+#endif
+#ifdef __NT__
+        || !stricmp(pszBase, "4nt.exe")
+        || !stricmp(pszBase, "tcc.exe")
+#endif
+        || !stricmp(pszBase, "command.com")
+        || !stricmp(pszBase, "4dos.com")
+       )
+    {
+        memcpy(pszCmdLineOpt, "/c", sizeof("/c"));
+        fIsUnixShell = 0;
+    }
+    else
+        memcpy(pszCmdLineOpt, "-c", sizeof("-c"));
+
+    /*
+     * Offset of argv[0] into pszShell.  Only do this for unix shell, at least
+     * for now.
+     */
+    if (fIsUnixShell == -1)
+    {
+        fIsUnixShell = !stricmp(pszBase, "sh.exe")   || !stricmp(pszBase, "sh")
+                    || !stricmp(pszBase, "ash.exe")  || !stricmp(pszBase, "ash")
+                    || !stricmp(pszBase, "bash.exe") || !stricmp(pszBase, "bash")
+                    || !stricmp(pszBase, "kash.exe") || !stricmp(pszBase, "kash");
+    }
+    if (fIsUnixShell)
+        *poffShellArg = pszBase - pszShell;
+    else
+        *poffShellArg = 0;
+
+    return 0;
+}
+
