Index: /trunk/src/kash/Makefile.kmk
===================================================================
--- /trunk/src/kash/Makefile.kmk	(revision 2651)
+++ /trunk/src/kash/Makefile.kmk	(revision 2652)
@@ -42,8 +42,9 @@
 ## @todo bring over PC_SLASHES?
 kash_DEFS.win = \
-	BSD PC_PATH_SEP PC_DRIVE_LETTERS PC_EXE_EXTS YY_NO_UNISTD_H SH_DEAL_WITH_CRLF
+	BSD YY_NO_UNISTD_H \
+	SH_DEAL_WITH_CRLF PC_PATH_SEP PC_DRIVE_LETTERS PC_EXE_EXTS EXEC_HASH_BANG_SCRIPT
 kash_DEFS.os2 = \
-	HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME \
-	EXEC_HASH_BANG_SCRIPT PC_OS2_LIBPATHS PC_PATH_SEP PC_DRIVE_LETTERS PC_EXE_EXTS
+	HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME PC_OS2_LIBPATHS \
+	SH_DEAL_WITH_CRLF PC_PATH_SEP PC_DRIVE_LETTERS PC_EXE_EXTS EXEC_HASH_BANG_SCRIPT
 kash_DEFS.darwin = \
 	HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME
Index: /trunk/src/kash/exec.c
===================================================================
--- /trunk/src/kash/exec.c	(revision 2651)
+++ /trunk/src/kash/exec.c	(revision 2652)
@@ -265,8 +265,9 @@
 	char **ap;
 	char *newargs[NEWARGS];
-	int i;
+	intptr_t i;
 	char **ap2;
 	char **new;
 
+	/* Split the string into arguments. */
 	n = psh->parsenleft - 2;
 	inp = psh->parsenextc + 2;
@@ -290,15 +291,22 @@
 	}
 
-	/* Special optimizations / builtins. */
+	/* /usr/bin/env emulation, very common with kash/kmk_ash. */
 	i = ap - newargs;
-	if (i > 1 && equal(newargs[0], "/usr/bin/env"))  {
-		/* /usr/bin/env <self> -> easy. */
-		if (i == 2 && is_shell_exe_name(newargs[1])) {
-		    TRACE((psh, "hash bang /usr/bin/env self\n"));
-		    return;
-		}
-		/** @todo implement simple /usr/bin/env that locates an exec in the PATH. */
-
-	} else if (i == 1) { /* if no args, maybe shell and no exec is needed. */
+	if (i > 1 && equal(newargs[0], "/usr/bin/env")) {
+		if (   !strchr(newargs[1], '=')
+		    && newargs[1][0] != '-') {
+		    /* shellexec below searches the PATH for us, so just
+		       drop /usr/bin/env. */
+		    TRACE((psh, "hash bang /usr/bin/env utility, dropping /usr/bin/env\n"));
+		    ap--;
+		    i--;
+		    for (n = 0; n < i; n++)
+			    newargs[n] = newargs[n + 1];
+		} /* else: complicated invocation */
+	}
+
+	/* If the interpreter is the shell or a similar shell, there is
+	   no need to exec. */
+	if (i == 1) {
 		p = strrchr(newargs[0], '/');
 		if (!p)
@@ -310,5 +318,5 @@
 	}
 
-	/* Combine the argument lists and exec. */
+	/* Combine the two argument lists and exec. */
 	i = (char *)ap - (char *)newargs;		/* size in bytes */
 	if (i == 0)
Index: /trunk/src/kash/generated/init.c
===================================================================
--- /trunk/src/kash/generated/init.c	(revision 2651)
+++ /trunk/src/kash/generated/init.c	(revision 2652)
@@ -268,6 +268,8 @@
 	      for (i = 0; psh->optlist[i].name; i++)
 		      psh->optlist[i].val = 0;
+# if DEBUG == 2
+	      debug(psh) = 1;
+# endif
 	      optschanged(psh);
-
       }
 
Index: /trunk/src/kash/options.c
===================================================================
--- /trunk/src/kash/options.c	(revision 2651)
+++ /trunk/src/kash/options.c	(revision 2652)
@@ -261,6 +261,8 @@
 	for (i = 0; psh->optlist[i].name; i++)
 		psh->optlist[i].val = 0;
+# if DEBUG == 2
+	debug(psh) = 1;
+# endif
 	optschanged(psh);
-
 }
 #endif
Index: /trunk/src/kash/shfile.c
===================================================================
--- /trunk/src/kash/shfile.c	(revision 2651)
+++ /trunk/src/kash/shfile.c	(revision 2652)
@@ -164,12 +164,12 @@
 static void shfile_native_close(intptr_t native, unsigned flags)
 {
-#if K_OS == K_OS_WINDOWS
+# if K_OS == K_OS_WINDOWS
     BOOL fRc = CloseHandle((HANDLE)native);
     assert(fRc); (void)fRc;
-#else
+# else
     int s = errno;
     close(native);
     errno = s;
-#endif
+# endif
     (void)flags;
 }
@@ -289,5 +289,5 @@
 }
 
-#if K_OS != K_OS_WINDOWS
+# if K_OS != K_OS_WINDOWS
 /**
  * Makes a copy of the native file, closes the original, and inserts the copy
@@ -318,5 +318,5 @@
     return fd;
 }
-#endif /* !K_OS_WINDOWS */
+# endif /* !K_OS_WINDOWS */
 
 /**
@@ -385,5 +385,5 @@
     }
     if (    *path == '/'
-#if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
+# if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
         ||  *path == '\\'
         ||  (   *path
@@ -391,5 +391,5 @@
              && (   (*path >= 'A' && *path <= 'Z')
                  || (*path >= 'a' && *path <= 'z')))
-#endif
+# endif
         )
     {
@@ -419,8 +419,8 @@
     }
 
-#if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
+# if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
     if (!strcmp(buf, "/dev/null"))
         strcpy(buf, "NUL");
-#endif
+# endif
     return 0;
 }
@@ -528,4 +528,19 @@
 
 /**
+ * Converts DOS slashes to UNIX slashes if necessary.
+ *
+ * @param   pszPath             The path to fix.
+ */
+static void shfile_fix_slashes(char *pszPath)
+{
+#if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
+    while ((pszPath = strchr(pszPath, '\\')))
+        *pszPath++ = '/';
+#else
+    (void)pszPath;
+#endif
+}
+
+/**
  * Initializes the global variables in this file.
  */
@@ -574,12 +589,5 @@
         if (getcwd(buf, sizeof(buf)))
         {
-# if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
-            char *pszSlash = strchr(buf, '\\');
-            while (pszSlash)
-            {
-                *pszSlash = '/';
-                pszSlash = strchr(pszSlash + 1, '\\');
-            }
-# endif
+            shfile_fix_slashes(buf);
 
             pfdtab->cwd = sh_strdup(NULL, buf);
@@ -1390,7 +1398,13 @@
         rc = -1;
 
-#else
+# ifdef DEBUG
     if (fd != shthread_get_shell()->tracefd)
-    {
+        TRACE2((NULL, "shfile_write(%d,,%d) -> %d [%d]\n", fd, len, rc, errno));
+# endif
+
+#else
+    if (fd != shthread_get_shell()->tracefd)
+    {
+        int iSavedErrno = errno;
         struct stat s;
         int x;
@@ -1398,19 +1412,8 @@
         TRACE2((NULL, "shfile_write(%d) - %lu bytes (%d) - pos %lu - before; %o\n",
                 fd, (long)s.st_size, x, (long)lseek(fd, 0, SEEK_CUR), s.st_mode ));
-        errno = 0;
+        errno = iSavedErrno;
     }
 
     rc = write(fd, buf, len);
-#endif
-
-#ifdef DEBUG
-    if (fd != shthread_get_shell()->tracefd)
-    {
-        struct stat s;
-        int x;
-        TRACE2((NULL, "shfile_write(%d,,%d) -> %d [%d]\n", fd, len, rc, errno));
-        x=fstat(fd, &s);
-        TRACE2((NULL, "shfile_write(%d) - %lu bytes (%d) - pos %lu - after\n", fd, (long)s.st_size, x, (long)lseek(fd, 0, SEEK_CUR) ));
-    }
 #endif
     return rc;
@@ -1601,5 +1604,5 @@
         char *abspath_copy = sh_strdup(psh, abspath);
         char *free_me = abspath_copy;
-        rc = chdir(path);
+        rc = chdir(abspath);
         if (!rc)
         {
@@ -1607,4 +1610,5 @@
             shmtx_enter(&pfdtab->mtx, &tmp);
 
+            shfile_fix_slashes(abspath_copy);
             free_me = pfdtab->cwd;
             pfdtab->cwd = abspath_copy;
Index: /trunk/src/kash/shinstance.c
===================================================================
--- /trunk/src/kash/shinstance.c	(revision 2651)
+++ /trunk/src/kash/shinstance.c	(revision 2652)
@@ -598,8 +598,19 @@
 #ifdef _MSC_VER
         if (signal(signo, g_sig_state[signo].sa.sa_handler) == SIG_ERR)
+        {
+            TRACE2((psh, "sh_sigaction: SIG_ERR, errno=%d signo=%d\n", errno, signo));
+            if (   signo != SIGHUP   /* whatever */
+                && signo != SIGQUIT
+                && signo != SIGPIPE
+                && signo != SIGTTIN
+                && signo != SIGTSTP
+                && signo != SIGTTOU
+                && signo != SIGCONT)
+                assert(0);
+        }
 #else
         if (sigaction(signo, &g_sig_state[signo].sa, NULL))
-#endif
             assert(0);
+#endif
 
         shmtx_leave(&g_sh_mtx, &tmp);
@@ -1181,4 +1192,19 @@
             errno = EINVAL;
         }
+        else
+        {
+            DWORD dwErr = GetLastError();
+            switch (dwErr)
+            {
+                case ERROR_FILE_NOT_FOUND:          errno = ENOENT; break;
+                case ERROR_PATH_NOT_FOUND:          errno = ENOENT; break;
+                case ERROR_BAD_EXE_FORMAT:          errno = ENOEXEC; break;
+                case ERROR_INVALID_EXE_SIGNATURE:   errno = ENOEXEC; break;
+                default:
+                    errno = EINVAL;
+                    break;
+            }
+            TRACE2((psh, "sh_execve: dwErr=%d -> errno=%d\n", dwErr, errno));
+        }
 
         shfile_exec_win(&psh->fdtab, 0 /* done */, NULL, NULL);
