Index: branches/libc-0.6/src/emx/include/include.smak
===================================================================
--- branches/libc-0.6/src/emx/include/include.smak	(revision 3643)
+++ branches/libc-0.6/src/emx/include/include.smak	(revision 3645)
@@ -58,2 +58,6 @@
 $(INS)include/InnoTekLIBC/%.h: include/InnoTekLIBC/%.h
 	$(call CP,$<,$@)
+	
+INS.FILES += $(addprefix $(INS), $(wildcard include/klibc/*.h))
+$(INS)include/klibc/%.h: include/klibc/%.h
+	$(call CP,$<,$@)	
Index: branches/libc-0.6/src/emx/include/klibc/startup.h
===================================================================
--- branches/libc-0.6/src/emx/include/klibc/startup.h	(revision 3645)
+++ branches/libc-0.6/src/emx/include/klibc/startup.h	(revision 3645)
@@ -0,0 +1,59 @@
+/* $Id$ */
+/** @file
+ * kLIBC startup stuff.
+ * 
+ *
+ * Copyright (c) 2008 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ *
+ * This file is part of kLIBC.
+ *
+ * kLIBC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * kLIBC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with kLIBC; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+/** @name Flags at argv[x][-1].
+ * @remarks Only on OS/2 and NT.
+ * @remarks Compatible with the _ARG_* stuff in emx/startup.h.
+ * @{ */
+#define __KLIBC_ARG_SIGNATURE   "\177kLIBC\177"
+/** This a filler to make sure the flag char isn't zero. */
+#define __KLIBC_ARG_NONZERO     0x80    
+/** Mask out the actual flags. */
+#define __KLIBC_ARG_MASK        0x3f
+/** Argument was double quoted. */
+#define __KLIBC_ARG_DQUOTE      0x01
+/** Argument was read from response file. */
+#define __KLIBC_ARG_RESPONSE    0x02
+/** Argument was expaneded from wildcard. */
+#define __KLIBC_ARG_WILDCARD    0x04
+/** Argument was expaneded from environment. */
+#define __KLIBC_ARG_ENV         0x08
+/** Argument was expanded by the shell. */
+#define __KLIBC_ARG_SHELL       0x10
+/** Argument was passed via a unix argv. */
+#define __KLIBC_ARG_ARGV        0x20
+/** @} */
+
+/** @name OS/2 Stub info.
+ * @{ */
+/** The stub signature of kLIBC binaries. */
+#define __KLIBC_STUB_SIGNATURE_BASE     "OS/2 executable module built for kLIBC v"
+/** The of the signature from the start of the executable. */
+#define __KLIBC_STUB_SIGNATURE_OFF      0x40
+/** The minimum size of a kLIBC binary. */
+#define __KLIBC_STUB_MIN_SIZE           0x80
+/** @} */
Index: branches/libc-0.6/src/emx/include/sys/process.h
===================================================================
--- branches/libc-0.6/src/emx/include/sys/process.h	(revision 3643)
+++ branches/libc-0.6/src/emx/include/sys/process.h	(revision 3645)
@@ -43,4 +43,5 @@
 #define P_UNRELATED  0x40000
 #define P_DEBUGDESC  0x80000
+#define P_NOUNIXARGV 0x100000
 
 #endif
Index: branches/libc-0.6/src/emx/src/lib/misc/response.c
===================================================================
--- branches/libc-0.6/src/emx/src/lib/misc/response.c	(revision 3643)
+++ branches/libc-0.6/src/emx/src/lib/misc/response.c	(revision 3645)
@@ -5,5 +5,5 @@
 #include <stdlib.h>
 #include <string.h>
-#include <emx/startup.h>
+#include <klibc/startup.h>
 
 #define RPUT(x) do \
@@ -30,5 +30,5 @@
   for (i = 1; i < old_argc; ++i)
     if (old_argv[i] != NULL
-        && !(old_argv[i][-1] & (_ARG_DQUOTE|_ARG_WILDCARD))
+        && !(old_argv[i][-1] & (__KLIBC_ARG_DQUOTE | __KLIBC_ARG_WILDCARD | __KLIBC_ARG_SHELL))
         && old_argv[i][0] == '@')
       break;
@@ -39,5 +39,5 @@
     {
       if (i == 0 || old_argv[i] == NULL
-          || (old_argv[i][-1] & (_ARG_DQUOTE|_ARG_WILDCARD))
+          || (old_argv[i][-1] & (__KLIBC_ARG_DQUOTE | __KLIBC_ARG_WILDCARD | __KLIBC_ARG_SHELL))
           || old_argv[i][0] != '@'
           || (f = fopen (old_argv[i]+1, "rt")) == NULL)
@@ -45,5 +45,5 @@
       else
         {
-          line[0] = _ARG_NONZERO|_ARG_RESPONSE;
+          line[0] = __KLIBC_ARG_NONZERO | __KLIBC_ARG_RESPONSE;
           while (fgets (line+1, sizeof (line)-1, f) != NULL)
             {
Index: branches/libc-0.6/src/emx/src/lib/misc/wildcard.c
===================================================================
--- branches/libc-0.6/src/emx/src/lib/misc/wildcard.c	(revision 3643)
+++ branches/libc-0.6/src/emx/src/lib/misc/wildcard.c	(revision 3645)
@@ -5,6 +5,6 @@
 #include <stdlib.h>
 #include <string.h>
-#include <emx/startup.h>
 #include <emx/syscalls.h>
+#include <klibc/startup.h>
 
 #define WPUT(x) do { \
@@ -32,5 +32,5 @@
   for (i = 1; i < old_argc; ++i)
     if (old_argv[i] != NULL &&
-        !(old_argv[i][-1] & (_ARG_DQUOTE|_ARG_RESPONSE)) &&
+        !(old_argv[i][-1] & (__KLIBC_ARG_DQUOTE | __KLIBC_ARG_RESPONSE | __KLIBC_ARG_ARGV | __KLIBC_ARG_SHELL)) &&
         strpbrk (old_argv[i], "?*") != NULL)
       break;
@@ -41,5 +41,5 @@
     {
       if (i == 0 || old_argv[i] == NULL
-          || (old_argv[i][-1] & (_ARG_DQUOTE|_ARG_RESPONSE))
+          || (old_argv[i][-1] & (__KLIBC_ARG_DQUOTE | __KLIBC_ARG_RESPONSE | __KLIBC_ARG_ARGV | __KLIBC_ARG_SHELL))
           || strpbrk (old_argv[i], "?*") == NULL
           || __findfirst (old_argv[i], 0x10, &find) != 0)
@@ -47,5 +47,5 @@
       else
         {
-          line[0] = _ARG_NONZERO|_ARG_WILDCARD;
+          line[0] = __KLIBC_ARG_NONZERO | __KLIBC_ARG_WILDCARD;
           strcpy (line+1, old_argv[i]);
           p = _getname (line + 1);
Index: branches/libc-0.6/src/emx/src/lib/sys/__init.c
===================================================================
--- branches/libc-0.6/src/emx/src/lib/sys/__init.c	(revision 3643)
+++ branches/libc-0.6/src/emx/src/lib/sys/__init.c	(revision 3645)
@@ -32,4 +32,5 @@
 #define __LIBC_LOG_GROUP    __LIBC_LOG_GRP_INITTERM
 #include <InnoTekLIBC/logstrict.h>
+#include <klibc/startup.h>
 #include "b_signal.h"
 
@@ -45,5 +46,5 @@
 *******************************************************************************/
 static int parse_args(const char *src, char **argv, char *pool);
-static int verify_end_of_single_quote(const char *src);
+/*static int verify_end_of_single_quote(const char *src);*/
 
 
@@ -81,4 +82,5 @@
 {
     int   quote;
+    char  ch;
     char  flags; 
     char *flag_ptr;
@@ -97,93 +99,139 @@
     }
     ++src;
-    for (;;)
+
+    /* Check for the kLIBC signature used for unix arguments. */
+    if (    src[0] != '\177'
+        ||  src[1] != 'k'
+        ||  src[2] != 'L'
+        ||  src[3] != 'I'
+        ||  src[4] != 'B'
+        ||  src[5] != 'C'
+        ||  src[6] != '\177'
+        ||  src[7] != '\0')
     {
-        while (WHITE(*src))
-            ++src;
-        if (*src == 0)
-            break;
-        if (!pool)
+        /* Convert from OS/2 command line convention to C/Unix. */
+        for (;;)
         {
-            flags = _ARG_NONZERO;
-            flag_ptr = &flags;
-            arg_size++;
+            while (WHITE(*src))
+                ++src;
+            if (*src == 0)
+                break;
+            if (!pool)
+            {
+                flags = _ARG_NONZERO;
+                flag_ptr = &flags;
+                arg_size++;
+            }
+            else
+            {
+                flag_ptr = pool;
+                PUTC((char)_ARG_NONZERO);
+            }
+            arg_pos = arg_size;
+            PUTV;
+            quote = 0;
+            for (;;)
+            {
+                /* End quote. */
+                if (*src == quote && quote)
+                    quote = 0;
+                /* Start of double quote. */
+                else if (!quote && *src == '"')
+                {
+                    quote = '"';
+                    *flag_ptr |= _ARG_DQUOTE;
+                }
+                /* 
+                 * Only permit the single quote to be used at the start of an argument or
+                 * within an already quoted one. This restriction is necessary to support
+                 * unquoted filenames containing the single quote char. 
+                 */
+                else if (   !quote && *src == '\'' 
+                         && (   arg_pos == arg_size 
+                             || (*flag_ptr & _ARG_DQUOTE)))
+                {
+                    quote = '\'';
+                    *flag_ptr |= _ARG_DQUOTE;
+                }
+                /* 
+                 * The escape character. This is truly magic/weird. 
+                 * It doesn't escape anything unless it's in front of a 
+                 * double quote character. EMX weirdness...
+                 * (Ok, not escaping more than necessary is ok when using \ as path 
+                 * separator, but why weird interpretation of \\\\"asdf"?
+                 */
+                else if (*src == '\\' && quote != '\'')
+                {
+                    int cSlashes = 0;
+                    do
+                    {
+                        cSlashes++;
+                        src++;
+                    } while (*src == '\\');
+    
+                    if (*src == '"')
+                    {
+                        /* Treat it is as escapes. */
+                        while (cSlashes >= 2)
+                        {
+                            PUTC('\\');
+                            cSlashes -= 2;
+                        }
+                        if (cSlashes & 1)
+                            PUTC(*src);
+                        else
+                            src--;
+                    }
+                    else
+                    {
+                        /* unmodified, no escaping. */
+                        while (cSlashes-- > 0)
+                            PUTC('\\');
+                        src--;
+                    }
+                }
+                /* Check for end of argument. */
+                else if (*src == 0 || (WHITE(*src) && !quote))
+                    break;
+                /* Normal character. */
+                else
+                    PUTC(*src);
+                ++src;
+            }
+            PUTC(0);
+        }
+    }
+    else
+    {
+        /* The kLIBC spawn packs exactly what we want, including the flag at [-1]. */
+        src += sizeof(__KLIBC_ARG_SIGNATURE);
+        if (pool)
+        {
+            /* copying */
+            while (*src)
+            {
+                LIBC_ASSERT((unsigned)*src & __KLIBC_ARG_NONZERO);
+                argc++;
+                *argv++ = pool + 1;
+                do
+                {
+                    *pool++ = ch = *src++;
+                } while (ch);
+            }
         }
         else
         {
-            flag_ptr = pool;
-            PUTC((char)_ARG_NONZERO);
+            /* counting */
+            while (*src)
+            {
+                LIBC_ASSERT((unsigned)*src & __KLIBC_ARG_NONZERO);
+                argc++;
+                do
+                {
+                    arg_size++;
+                    ch = *src++;
+                } while (ch);
+            }
         }
-        arg_pos = arg_size;
-        PUTV;
-        quote = 0;
-        for (;;)
-        {
-            /* End quote. */
-            if (*src == quote && quote)
-                quote = 0;
-            /* Start of double quote. */
-            else if (!quote && *src == '"')
-            {
-                quote = '"';
-                *flag_ptr |= _ARG_DQUOTE;
-            }
-            /* 
-             * Only permit the single quote to be used at the start of an argument or
-             * within an already quoted one. This restriction is necessary to support
-             * unquoted filenames containing the single quote char. 
-             */
-            else if (   !quote && *src == '\'' 
-                     && (   arg_pos == arg_size 
-                         || (*flag_ptr & _ARG_DQUOTE)))
-            {
-                quote = '\'';
-                *flag_ptr |= _ARG_DQUOTE;
-            }
-            /* 
-             * The escape character. This is truly magic/weird. 
-             * It doesn't escape anything unless it's in front of a 
-             * double quote character. EMX weirdness...
-             * (Ok, not escaping more than necessary is ok when using \ as path 
-             * separator, but why weird interpretation of \\\\"asdf"?
-             */
-            else if (*src == '\\' && quote != '\'')
-            {
-                int cSlashes = 0;
-                do
-                {
-                    cSlashes++;
-                    src++;
-                } while (*src == '\\');
-
-                if (*src == '"')
-                {
-                    /* Treat it is as escapes. */
-                    while (cSlashes >= 2)
-                    {
-                        PUTC('\\');
-                        cSlashes -= 2;
-                    }
-                    if (cSlashes & 1)
-                        PUTC(*src);
-                    else
-                        src--;
-                }
-                else
-                {
-                    /* unmodified, no escaping. */
-                    while (cSlashes-- > 0)
-                        PUTC('\\');
-                    src--;
-                }
-            }
-            /* Check for end of argument. */
-            else if (*src == 0 || (WHITE(*src) && !quote))
-                break;
-            /* Normal character. */
-            else
-                PUTC(*src);
-            ++src;
-        }
-        PUTC(0);
     }
     return arg_size;
@@ -191,4 +239,5 @@
 
 
+#if 0
 /**
  * This is a hack to prevent us from messing up filenames that 
@@ -200,4 +249,5 @@
  */
 static int verify_end_of_single_quote(const char *src);
+#endif 
 
 
Index: branches/libc-0.6/src/emx/src/lib/sys/__spawnve.c
===================================================================
--- branches/libc-0.6/src/emx/src/lib/sys/__spawnve.c	(revision 3643)
+++ branches/libc-0.6/src/emx/src/lib/sys/__spawnve.c	(revision 3645)
@@ -19,4 +19,5 @@
 #include <InnoTekLIBC/sharedpm.h>
 #include <InnoTekLIBC/backend.h>
+#include <klibc/startup.h>
 #define __LIBC_LOG_GROUP    __LIBC_LOG_GRP_PROCESS
 #include <InnoTekLIBC/logstrict.h>
@@ -179,4 +180,5 @@
     LIBCLOG_ENTER("np=%p:{mode=%#x}\n", (void *)np, np->mode);
     FS_VAR();
+    char szLineBuf[512];
 
     /*
@@ -220,10 +222,54 @@
 
     /*
-     * cmd.exe and 4os2.exe needs different argument handling.
+     * cmd.exe and 4os2.exe needs different argument handling, and 
+     * starting with kLIBC 0.6.4 we can pass argv directly to LIBC 
+     * programs.
      * (1 == cmd or 4os2 shell, 0 == anything else)
      */
+    enum { args_standard, args_cmd, args_unix } enmMethod = args_standard;
     char *psz = _getname(pszPgmName);
-    int method = stricmp(psz, "cmd.exe") == 0
-              || stricmp(psz, "4os2.exe") == 0;
+    if (   stricmp(psz, "cmd.exe") == 0
+        || stricmp(psz, "4os2.exe") == 0)
+        enmMethod = args_cmd;
+    else
+    {
+        HFILE hFile = NULLHANDLE;
+        ULONG ulAction = 0;
+        rc = DosOpen((PCSZ)pszPgmName, &hFile, &ulAction, 0, FILE_NORMAL,
+                     OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
+                     OPEN_FLAGS_SEQUENTIAL | OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY,
+                     NULL);
+        if (!rc)
+        {
+            ULONG cbRead = 0;
+            rc = DosRead(hFile, szLineBuf, sizeof(szLineBuf), &cbRead);
+            DosClose(hFile);
+            if (rc)
+                LIBCLOG_ERROR("DosRead - rc=%d (%s)\n", rc, pszPgmName);
+            else if (   cbRead >= __KLIBC_STUB_MIN_SIZE
+                     && szLineBuf[0] == 'M'
+                     && szLineBuf[1] == 'Z'
+                     && !memcmp(&szLineBuf[__KLIBC_STUB_SIGNATURE_OFF], __KLIBC_STUB_SIGNATURE_BASE, sizeof(__KLIBC_STUB_SIGNATURE_BASE) - 1)
+                    )
+            {
+                char const *pchVer = &szLineBuf[__KLIBC_STUB_SIGNATURE_OFF + sizeof(__KLIBC_STUB_SIGNATURE_BASE) - 1];
+                if (*pchVer >= '0' && *pchVer <= '9')
+                    enmMethod = !(np->mode & P_NOUNIXARGV) ? args_unix : args_standard;
+            }
+            /** @todo move the hash bang handling up here. */
+            /*else if (!rc && szLineBuf[0] == '#')
+            {
+            } */
+        }
+        /* Catch some plain failures here, leave the rest for later. */
+        else if (   rc == ERROR_FILE_NOT_FOUND
+                 || rc == ERROR_PATH_NOT_FOUND)
+        {
+            _sys_set_errno(rc);
+            LIBCLOG_RETURN_INT(-1);
+        }
+        else
+            LIBCLOG_ERROR("rc=%d (%s)\n", rc, pszPgmName);
+    }
 
     /*
@@ -235,4 +281,6 @@
     char       *pszArg = NULL;
     size_t      cbArgs = 0;
+    int         i;
+
     if (np->arg_count > 0)
     {
@@ -243,72 +291,100 @@
         pszArg += cch; pszSrc += cch;
     }
-    int i;
-    for (i = 1; i < np->arg_count; ++i)
+    if (enmMethod == args_unix)
     {
-        if (i > 1)
+        /* first arg is the signature. */
+        ADD(sizeof(__KLIBC_ARG_SIGNATURE));
+        memcpy(pszArg, __KLIBC_ARG_SIGNATURE, sizeof(__KLIBC_ARG_SIGNATURE));
+        pszArg += sizeof(__KLIBC_ARG_SIGNATURE);
+
+        /* then comes the argument vector. */
+        for (i = 1; i < np->arg_count; ++i)
         {
-            ADD(1);
-            *pszArg++ = ' ';
+            unsigned char chFlags = *pszSrc++;
+            chFlags &= __KLIBC_ARG_MASK;
+            chFlags |= __KLIBC_ARG_ARGV;
+            cch = strlen(pszSrc) + 1;
+            ADD(cch + 1);
+            *pszArg++ = chFlags;
+            memcpy(pszArg, pszSrc, cch);
+            pszArg += cch;
+            pszSrc += cch;
         }
-        ++pszSrc;                    /* skip flags byte */
-        BOOL fQuote = FALSE;
-        if (*pszSrc == 0)
-            fQuote = TRUE;
-        else if (ulMode & P_QUOTE)
+
+        /* the double termination. */
+        ADD(1);
+        *pszArg = '\0';
+    }
+    else
+    {
+        /* quote the arguments in emx / cmd.exe fashion. */
+        for (i = 1; i < np->arg_count; ++i)
         {
-            if (pszSrc[0] == '@' && pszSrc[1] != 0)
+            if (i > 1)
+            {
+                ADD(1);
+                *pszArg++ = ' ';
+            }
+            ++pszSrc;                    /* skip flags byte */
+            BOOL fQuote = FALSE;
+            if (*pszSrc == 0)
                 fQuote = TRUE;
-            else
+            else if (ulMode & P_QUOTE)
+            {
+                if (pszSrc[0] == '@' && pszSrc[1] != 0)
+                    fQuote = TRUE;
+                else
+                    for (psz = (char *)pszSrc; *psz != 0; ++psz)
+                        if (*psz == '?' || *psz == '*')
+                        {
+                            fQuote = TRUE;
+                            break;
+                        }
+            }
+            if (!fQuote)
+            {
                 for (psz = (char *)pszSrc; *psz != 0; ++psz)
-                    if (*psz == '?' || *psz == '*')
+                    if (*psz == ' ' || *psz == '\t' || (*psz == '"' && enmMethod == args_cmd))
                     {
                         fQuote = TRUE;
                         break;
                     }
-        }
-        if (!fQuote)
-        {
-            for (psz = (char *)pszSrc; *psz != 0; ++psz)
-                if (*psz == ' ' || *psz == '\t' || (*psz == '"' && method == 1))
+            }
+            if (fQuote)
+            {
+                ADD(1);
+                *pszArg++ = '"';
+            }
+            size_t bs = 0;
+            while (*pszSrc != 0)
+            {
+                if (*pszSrc == '"' && enmMethod == args_standard)
                 {
-                    fQuote = TRUE;
-                    break;
+                    ++bs;
+                    ADD(bs);
+                    memset(pszArg, '\\', bs); pszArg += bs;
+                    bs = 0;
                 }
-        }
-        if (fQuote)
-        {
-            ADD(1);
-            *pszArg++ = '"';
-        }
-        size_t bs = 0;
-        while (*pszSrc != 0)
-        {
-            if (*pszSrc == '"' && method == 0)
-            {
-                ++bs;
-                ADD(bs);
+                else if (*pszSrc == '\\' && enmMethod == args_standard)
+                    ++bs;
+                else
+                    bs = 0;
+                ADD(1);
+                *pszArg++ = *pszSrc;
+                ++pszSrc;
+            }
+            if (fQuote)
+            {
+                ADD(1+bs);
                 memset(pszArg, '\\', bs); pszArg += bs;
-                bs = 0;
-            }
-            else if (*pszSrc == '\\' && method == 0)
-                ++bs;
-            else
-                bs = 0;
-            ADD(1);
-            *pszArg++ = *pszSrc;
+                *pszArg++ = '"';
+            }
             ++pszSrc;
         }
-        if (fQuote)
-        {
-            ADD(1+bs);
-            memset(pszArg, '\\', bs); pszArg += bs;
-            *pszArg++ = '"';
-        }
-        ++pszSrc;
+        /* The arguments are an array of zero terminated strings, ending with an empty string. */
+        ADD(2);
+        *pszArg++ = '\0';
+        *pszArg++ = '\0';
     }
-    /* The arguments are an array of zero terminated strings, ending with an empty string. */
-    ADD(2);
-    *pszArg++ = '\0';
-    *pszArg++ = '\0';
 
 
@@ -345,5 +421,4 @@
                  * requires inspection of the first line of the file.
                  */
-                char szLineBuf[256];
                 const char *pszInterpreter = NULL;
                 const char *pszInterpreterArgs = NULL;
