changeset 21949:baeffde5c87d

fix build for Windows systems * file-stat.cc, oct-syscalls.cc, syscalls.cc: Include <ctime>. * sysdep.cc: Include <shellapi.h> for Windows. * lo-sysdep.cc: Include <fcntl.h> and <io.h> for Windows. * wait-wrappers.c (WIFCONTINUED): Define if sys/wait.h does not. * signal-wrappers.c (octave_kill_wrapper): Return -1 if kill is missing. * main.in.cc (prepare_spawn): Move to unistd-wrappers.c. (octave_exec): Eliminate special case for Windows. (main): Display message if exec fails. * unistd-wrappers.h, fcntl-wrappers.h, lo-sysdep.h: Include <sys/types.h> * unistd-wrappers.c (octave_execv_wrapper): Handle Windows implementation here. Free sanitized command vector if spawnv fails. (octave_getegid_wrapper): Return -1 if getegid is missing. (octave_geteuid_wrapper): Return -1 if geteuid is missing. (octave_getgid_wrapper): Return -1 if getgid is missing. (octave_getpgrp_wrapper): Return -1 if getpgrp is missing. (octave_getpid_wrapper): Return -1 if getpid is missing. (octave_getppid_wrapper): Return -1 if getppid is missing. (octave_getuid_wrapper): Return -1 if getuid is missing. (octave_setsid_wrapper): Return -1 if setsid is missing. * configure.ac: Check for setsid. * lo-sysdep.cc (win_popen2): Move to octave-popen2.c. * lo-sysdep.h (win_popen2): Delete decl. (octave_popen2): Delete deprecated function pointer. * octave-popen2, octave-popen2.c (octave_popen2): New arg, ERRMSG. Handle Windows implemenation here. (make_command_string): New static function. * oct-syscalls.cc (octave::sys::popen2): Eliminate special case for Windows. Defined deprecated inline functions for old octave_popen2 interface. * quit.h: Don't include <windows.h>. (w32_sigint_init, w32_raise_final, w32_raise, w32_in_main_thread): Delete decls of undefined and unused functions. * toplev.cc: Include <windows.h>. * sysdep.cc: Include <windows.h> before <tlhelp32.h> and <shellapi.h>.
author John W. Eaton <jwe@octave.org>
date Sat, 18 Jun 2016 10:55:49 -0400
parents 241d39c66e8f
children b76a0738a662
files configure.ac libinterp/corefcn/syscalls.cc libinterp/corefcn/sysdep.cc libinterp/corefcn/toplev.cc liboctave/cruft/misc/quit.h liboctave/system/file-stat.cc liboctave/system/lo-sysdep.cc liboctave/system/lo-sysdep.h liboctave/system/oct-syscalls.cc liboctave/system/oct-syscalls.h liboctave/wrappers/fcntl-wrappers.h liboctave/wrappers/octave-popen2.c liboctave/wrappers/octave-popen2.h liboctave/wrappers/signal-wrappers.c liboctave/wrappers/unistd-wrappers.c liboctave/wrappers/unistd-wrappers.h liboctave/wrappers/wait-wrappers.c src/main.in.cc
diffstat 18 files changed, 391 insertions(+), 252 deletions(-) [+]
line wrap: on
line diff
--- a/configure.ac	Fri Jun 17 15:18:58 2016 -0700
+++ b/configure.ac	Sat Jun 18 10:55:49 2016 -0400
@@ -2526,7 +2526,7 @@
 AC_CHECK_FUNCS([lgamma lgammaf lgamma_r lgammaf_r])
 AC_CHECK_FUNCS([log1p log1pf])
 AC_CHECK_FUNCS([realpath resolvepath roundl])
-AC_CHECK_FUNCS([select setgrent setpwent siglongjmp strsignal])
+AC_CHECK_FUNCS([select setgrent setpwent setsid siglongjmp strsignal])
 AC_CHECK_FUNCS([tcgetattr tcsetattr tgammaf toascii])
 AC_CHECK_FUNCS([umask waitpid])
 AC_CHECK_FUNCS([_getch _kbhit])
--- a/libinterp/corefcn/syscalls.cc	Fri Jun 17 15:18:58 2016 -0700
+++ b/libinterp/corefcn/syscalls.cc	Sat Jun 18 10:55:49 2016 -0400
@@ -30,6 +30,7 @@
 #  include "config.h"
 #endif
 
+#include <ctime>
 #include <cstdio>
 #include <cstring>
 
--- a/libinterp/corefcn/sysdep.cc	Fri Jun 17 15:18:58 2016 -0700
+++ b/libinterp/corefcn/sysdep.cc	Sat Jun 18 10:55:49 2016 -0400
@@ -109,8 +109,9 @@
 #if defined (__WIN32__) && ! defined (_POSIX_VERSION)
 
 #define WIN32_LEAN_AND_MEAN
+#include <windows.h>
 #include <tlhelp32.h>
-#include <windows.h>
+#include <shellapi.h>
 
 static void
 w32_set_octave_home (void)
--- a/libinterp/corefcn/toplev.cc	Fri Jun 17 15:18:58 2016 -0700
+++ b/libinterp/corefcn/toplev.cc	Sat Jun 18 10:55:49 2016 -0400
@@ -35,6 +35,11 @@
 #include <sstream>
 #include <string>
 
+#if defined (__WIN32__) && ! defined (__CYGWIN__)
+#  define WIN32_LEAN_AND_MEAN 1
+#  include <windows.h>
+#endif
+
 #include "cmd-edit.h"
 #include "cmd-hist.h"
 #include "file-ops.h"
--- a/liboctave/cruft/misc/quit.h	Fri Jun 17 15:18:58 2016 -0700
+++ b/liboctave/cruft/misc/quit.h	Sat Jun 18 10:55:49 2016 -0400
@@ -36,18 +36,6 @@
 #  include <signal.h>
 #endif
 
-#if defined (__WIN32__) && ! defined (_POSIX_VERSION)
-
-#define WIN32_LEAN_AND_MEAN 1
-#include <windows.h>
-
-OCTAVE_API extern void w32_sigint_init (void);   /* setup */
-OCTAVE_API extern void w32_raise_final (void);   /* tear down */
-OCTAVE_API extern void w32_raise (int sig);      /* raise signal in main thread */
-OCTAVE_API extern int w32_in_main_thread (void); /* return true if in main thread */
-
-#endif
-
 #if defined (OCTAVE_HAVE_SIG_JUMP)
 
 typedef sigjmp_buf octave_jmp_buf;
--- a/liboctave/system/file-stat.cc	Fri Jun 17 15:18:58 2016 -0700
+++ b/liboctave/system/file-stat.cc	Sat Jun 18 10:55:49 2016 -0400
@@ -24,6 +24,7 @@
 #  include "config.h"
 #endif
 
+#include <ctime>
 #include <cerrno>
 #include <cstring>
 
--- a/liboctave/system/lo-sysdep.cc	Fri Jun 17 15:18:58 2016 -0700
+++ b/liboctave/system/lo-sysdep.cc	Sat Jun 18 10:55:49 2016 -0400
@@ -24,20 +24,11 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
 #include <string>
-#include <vector>
-
-#if defined (__WIN32__) && ! defined (__CYGWIN__)
-#  define WIN32_LEAN_AND_MEAN 1
-#  include <windows.h>
-#endif
 
 #include "file-ops.h"
 #include "lo-error.h"
 #include "lo-sysdep.h"
-#include "oct-locbuf.h"
-#include "str-vec.h"
 #include "unistd-wrappers.h"
 
 namespace octave
@@ -76,79 +67,5 @@
 
       return octave_chdir_wrapper (path.c_str ());
     }
-
-#if defined (__WIN32__) && ! defined (__CYGWIN__)
-
-    // FIXME: this function could be combined with octave_popen2 in
-    // liboctave/wrappers/octave-popen2.c.
-
-    pid_t
-    win_popen2 (const std::string& cmd, const string_vector& args,
-                bool sync_mode, int *fildes, std::string& msg)
-    {
-      pid_t pid;
-      PROCESS_INFORMATION pi;
-      STARTUPINFO si;
-      std::string command = "\"" + cmd + "\"";
-      HANDLE hProcess = GetCurrentProcess ();
-      HANDLE childRead, childWrite, parentRead, parentWrite;
-      DWORD pipeMode;
-
-      ZeroMemory (&pi, sizeof (pi));
-      ZeroMemory (&si, sizeof (si));
-      si.cb = sizeof (si);
-
-      if (! CreatePipe (&childRead, &parentWrite, 0, 0)
-          || ! DuplicateHandle (hProcess, childRead, hProcess, &childRead,
-                                0, TRUE,
-                                DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
-        {
-          msg = "popen2: pipe creation failed";
-          return -1;
-        }
-      if (! CreatePipe (&parentRead, &childWrite, 0, 0)
-          || ! DuplicateHandle (hProcess, childWrite, hProcess, &childWrite,
-                                0, TRUE,
-                                DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
-        {
-          msg = "popen2: pipe creation failed";
-          return -1;
-        }
-      if (! sync_mode)
-        {
-          pipeMode = PIPE_NOWAIT;
-          SetNamedPipeHandleState (parentRead, &pipeMode, 0, 0);
-        }
-      fildes[1] = _open_osfhandle (reinterpret_cast<intptr_t> (parentRead),
-                                   _O_RDONLY | _O_BINARY);
-      fildes[0] = _open_osfhandle (reinterpret_cast<intptr_t> (parentWrite),
-                                   _O_WRONLY | _O_BINARY);
-      si.dwFlags |= STARTF_USESTDHANDLES;
-      si.hStdInput = childRead;
-      si.hStdOutput = childWrite;
-      si.hStdError = GetStdHandle (STD_ERROR_HANDLE);
-
-      // Ignore first arg as it is the command
-      for (int k=1; k<args.numel (); k++)
-        command += " \"" + args[k] + "\"";
-      OCTAVE_LOCAL_BUFFER (char, c_command, command.length () + 1);
-      strcpy (c_command, command.c_str ());
-      if (! CreateProcess (0, c_command, 0, 0, TRUE, 0, 0, 0, &si, &pi))
-        {
-          msg = "popen2: process creation failed";
-          return -1;
-        }
-      pid = pi.dwProcessId;
-
-      CloseHandle (childRead);
-      CloseHandle (childWrite);
-      CloseHandle (pi.hProcess);
-      CloseHandle (pi.hThread);
-
-      return pid;
-    }
-
-#endif
-
   }
 }
--- a/liboctave/system/lo-sysdep.h	Fri Jun 17 15:18:58 2016 -0700
+++ b/liboctave/system/lo-sysdep.h	Sat Jun 18 10:55:49 2016 -0400
@@ -27,6 +27,8 @@
 
 #include <string>
 
+#include <sys/types.h>
+
 #include "lo-ieee.h"
 
 class string_vector;
@@ -38,11 +40,6 @@
     extern std::string getcwd (void);
 
     extern int chdir (const std::string&);
-
-#if defined (__WIN32__) && ! defined (__CYGWIN__)
-    extern pid_t win_popen2 (const std::string&, const string_vector&,
-                             bool, int *, std::string&);
-#endif
   }
 }
 
@@ -54,11 +51,6 @@
 OCTAVE_DEPRECATED ("use 'octave::sys::chdir' instead")
 const auto octave_chdir = octave::sys::chdir;
 
-#if defined (__WIN32__) && ! defined (__CYGWIN__)
-OCTAVE_DEPRECATED ("use 'octave::sys::popen2' instead")
-const auto octave_popen2 = octave::sys::win_popen2;
 #endif
 
 #endif
-
-#endif
--- a/liboctave/system/oct-syscalls.cc	Fri Jun 17 15:18:58 2016 -0700
+++ b/liboctave/system/oct-syscalls.cc	Sat Jun 18 10:55:49 2016 -0400
@@ -24,6 +24,7 @@
 #  include "config.h"
 #endif
 
+#include <ctime>
 #include <cerrno>
 #include <cstdlib>
 #include <cstring>
@@ -339,23 +340,18 @@
             bool sync_mode, int *fildes, std::string& msg,
             bool & /* interactive */)
     {
-#if defined (__WIN32__) && ! defined (__CYGWIN__)
-      // FIXME: this function could be combined with octave_popen2 in
-      // liboctave/wrappers/octave-popen2.c.
+      char **argv = args.c_str_vec ();
+      const char *errmsg;
 
-      return octave::sys::win_popen2 (cmd, args, sync_mode, fildes, msg);
-#else
-      char **argv = args.c_str_vec ();
-
-      pid_t pid = octave_popen2 (cmd.c_str (), argv, sync_mode, fildes);
+      pid_t pid = octave_popen2 (cmd.c_str (), argv, sync_mode, fildes,
+                                 &errmsg);
 
       string_vector::delete_c_str_vec (argv);
 
       if (pid < 0)
-        msg = std::strerror (errno);
+        msg = errmsg;
 
       return pid;
-#endif
     }
 
     int
--- a/liboctave/system/oct-syscalls.h	Fri Jun 17 15:18:58 2016 -0700
+++ b/liboctave/system/oct-syscalls.h	Sat Jun 18 10:55:49 2016 -0400
@@ -107,5 +107,33 @@
   }
 }
 
+#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
+
+OCTAVE_DEPRECATED ("use 'octave::sys::popen2' instead")
+inline pid_t
+octave_popen2 (const std::string& cmd, const string_vector& args,
+               bool sync_mode, int *filedes)
+{
+  return octave::sys::popen2 (cmd, args, sync_mode, filedes);
+}
+
+OCTAVE_DEPRECATED ("use 'octave::sys::popen2' instead")
+inline pid_t
+popen2 (const std::string& cmd, const string_vector& args,
+        bool sync_mode, int *filedes, std::string& msg)
+{
+  return octave::sys::popen2 (cmd, args, sync_mode, filedes, msg);
+}
+
+OCTAVE_DEPRECATED ("use 'octave::sys::popen2' instead")
+inline pid_t
+popen2 (const std::string& cmd, const string_vector& args,
+        bool sync_mode, int *filedes, std::string& msg, bool &interactive)
+{
+  return octave::sys::popen2 (cmd, args, sync_mode, filedes, msg, interactive);
+}
+
 #endif
 
+#endif
+
--- a/liboctave/wrappers/fcntl-wrappers.h	Fri Jun 17 15:18:58 2016 -0700
+++ b/liboctave/wrappers/fcntl-wrappers.h	Sat Jun 18 10:55:49 2016 -0400
@@ -23,6 +23,8 @@
 #if ! defined (octave_fcntl_wrappers_h)
 #define octave_fcntl_wrappers_h 1
 
+#include <sys/types.h>
+
 #if defined __cplusplus
 extern "C" {
 #endif
--- a/liboctave/wrappers/octave-popen2.c	Fri Jun 17 15:18:58 2016 -0700
+++ b/liboctave/wrappers/octave-popen2.c	Sat Jun 18 10:55:49 2016 -0400
@@ -34,29 +34,149 @@
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
-
-#include <fcntl.h>
+#include <string.h>
 
-#include <sys/types.h>
-#include <unistd.h>
+#if defined (__WIN32__) && ! defined (__CYGWIN__)
+#  include <fcntl.h>
+#  include <io.h>
+#  define WIN32_LEAN_AND_MEAN 1
+#  include <windows.h>
+#else
+#  include <errno.h>
+#  include <fcntl.h>
+#  include <sys/types.h>
+#  include <unistd.h>
+#endif
 
 #include "octave-popen2.h"
 
+#if defined (__WIN32__) && ! defined (__CYGWIN__)
+
+static char *
+make_command_string (const char *cmd, char *const *args)
+{
+  char *const *argp;
+  size_t cmd_len;
+  char *command;
+
+  // Count Command length, quotes, and terminating NUL character.
+  cmd_len = strlen (cmd) + 3;
+
+  // Count argument length, space, and quotes.
+  // Ignore first arg as it is the command.
+  argp = args;
+  while (*++argp)
+    cmd_len += strlen (*argp) + 3;
+
+  command = (char *) malloc (cmd_len);
+
+  sprintf (command, "\"%s\"", cmd);
+
+  argp = args;
+  while (*++argp)
+    sprintf (command, "%s \"%s\"", command, *argp);
+
+  return command;
+}
+
 pid_t
-octave_popen2 (const char *cmd, char *const *args, bool sync_mode, int *fildes)
+octave_popen2 (const char *cmd, char *const *args, bool sync_mode,
+               int *fildes, const char **errmsg)
+{
+  pid_t pid;
+
+  char *command;
+  bool status;
+
+  PROCESS_INFORMATION pi;
+  STARTUPINFO si;
+
+  HANDLE hProcess = GetCurrentProcess ();
+  HANDLE childRead, childWrite, parentRead, parentWrite;
+  DWORD pipeMode;
+
+  ZeroMemory (&pi, sizeof (pi));
+  ZeroMemory (&si, sizeof (si));
+  si.cb = sizeof (si);
+
+  if (! CreatePipe (&childRead, &parentWrite, 0, 0)
+      || ! DuplicateHandle (hProcess, childRead, hProcess, &childRead,
+                            0, TRUE,
+                            DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
+    {
+      *errmsg = "popen2: pipe creation failed";
+      return -1;
+    }
+
+  if (! CreatePipe (&parentRead, &childWrite, 0, 0)
+      || ! DuplicateHandle (hProcess, childWrite, hProcess, &childWrite,
+                            0, TRUE,
+                            DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
+    {
+      *errmsg = "popen2: pipe creation failed";
+      return -1;
+    }
+
+  if (! sync_mode)
+    {
+      pipeMode = PIPE_NOWAIT;
+      SetNamedPipeHandleState (parentRead, &pipeMode, 0, 0);
+    }
+
+  fildes[1] = _open_osfhandle ((intptr_t) parentRead, _O_RDONLY | _O_BINARY);
+  fildes[0] = _open_osfhandle ((intptr_t) parentWrite, _O_WRONLY | _O_BINARY);
+
+  si.dwFlags |= STARTF_USESTDHANDLES;
+
+  si.hStdInput = childRead;
+  si.hStdOutput = childWrite;
+  si.hStdError = GetStdHandle (STD_ERROR_HANDLE);
+
+  command = make_command_string (cmd, args);
+
+  status = CreateProcess (0, command, 0, 0, TRUE, 0, 0, 0, &si, &pi);
+
+  free (command);
+
+  if (! status)
+    {
+      *errmsg = "popen2: process creation failed";
+      return -1;
+    }
+
+  pid = pi.dwProcessId;
+
+  CloseHandle (childRead);
+  CloseHandle (childWrite);
+
+  CloseHandle (pi.hProcess);
+  CloseHandle (pi.hThread);
+
+  return pid;
+}
+
+#else
+
+pid_t
+octave_popen2 (const char *cmd, char *const *args, bool sync_mode,
+               int *fildes, const char **errmsg)
 {
   pid_t pid;
 
   int child_stdin[2], child_stdout[2];
 
   if (pipe (child_stdin) < 0)
-    return -1;
+    {
+      *errmsg = strerror (errno);
+      return -1;
+    }
 
   if (pipe (child_stdout) < 0)
     {
       close (child_stdin[0]);
       close (child_stdin[1]);
 
+      *errmsg = strerror (errno);
       return -1;
     }
 
@@ -97,7 +217,10 @@
 
 #if defined (F_SETFL) && defined (O_NONBLOCK)
       if (! sync_mode && fcntl (child_stdout[0], F_SETFL, O_NONBLOCK) < 0)
-        return -1;
+        {
+          *errmsg = strerror (errno);
+          return -1;
+        }
       else
 #endif
         {
@@ -108,5 +231,9 @@
         }
     }
 
+  *errmsg = "foobar!";
+  *errmsg = strerror (errno);
   return pid;
 }
+
+#endif
--- a/liboctave/wrappers/octave-popen2.h	Fri Jun 17 15:18:58 2016 -0700
+++ b/liboctave/wrappers/octave-popen2.h	Sat Jun 18 10:55:49 2016 -0400
@@ -29,7 +29,7 @@
 
 extern pid_t
 octave_popen2 (const char *cmd, char *const *args, bool sync_mode,
-               int *fildes);
+               int *fildes, const char **errmsg);
 
 #if defined __cplusplus
 }
--- a/liboctave/wrappers/signal-wrappers.c	Fri Jun 17 15:18:58 2016 -0700
+++ b/liboctave/wrappers/signal-wrappers.c	Sat Jun 18 10:55:49 2016 -0400
@@ -45,7 +45,11 @@
 int
 octave_kill_wrapper (pid_t pid, int signum)
 {
+#if defined (HAVE_KILL)
   return kill (pid, signum);
+#else
+  return -1;
+#endif
 }
 
 char *
--- a/liboctave/wrappers/unistd-wrappers.c	Fri Jun 17 15:18:58 2016 -0700
+++ b/liboctave/wrappers/unistd-wrappers.c	Sat Jun 18 10:55:49 2016 -0400
@@ -36,6 +36,10 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#if defined (__WIN32__) && ! defined (__CYGWIN__)
+#  include <process.h>
+#endif
+
 #include "unistd-wrappers.h"
 
 int
@@ -96,10 +100,160 @@
   return dup2 (fd1, fd2);
 }
 
+#if defined (__WIN32__) && ! defined (__CYGWIN__)
+
+// Adapted from libtool wrapper.
+
+/* Prepares an argument vector before calling spawn().
+
+   Note that spawn() does not by itself call the command interpreter
+     (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
+      ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+         GetVersionEx(&v);
+         v.dwPlatformId == VER_PLATFORM_WIN32_NT;
+      }) ? "cmd.exe" : "command.com").
+
+   Instead it simply concatenates the arguments, separated by ' ', and calls
+   CreateProcess().  We must quote the arguments since Win32 CreateProcess()
+   interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
+   special way:
+
+   - Space and tab are interpreted as delimiters. They are not treated as
+     delimiters if they are surrounded by double quotes: "...".
+
+   - Unescaped double quotes are removed from the input. Their only effect is
+     that within double quotes, space and tab are treated like normal
+     characters.
+
+   - Backslashes not followed by double quotes are not special.
+
+   - But 2*n+1 backslashes followed by a double quote become
+     n backslashes followed by a double quote (n >= 0):
+       \" -> "
+       \\\" -> \"
+       \\\\\" -> \\"
+ */
+
+#define SHELL_SPECIAL_CHARS \
+  "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+
+#define SHELL_SPACE_CHARS \
+  " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+
+static char **
+prepare_spawn (char **argv)
+{
+  size_t argc;
+  char **new_argv;
+  size_t i;
+
+  /* Count number of arguments.  */
+  for (argc = 0; argv[argc] != NULL; argc++)
+    ;
+
+  /* Allocate new argument vector.  */
+  new_argv = (char **) malloc (argc + 1);
+
+  /* Put quoted arguments into the new argument vector.  */
+  for (i = 0; i < argc; i++)
+    {
+      const char *string = argv[i];
+
+      if (string[0] == '\0')
+        new_argv[i] = strdup ("\"\"");
+      else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
+        {
+          int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
+          size_t length;
+          unsigned int backslashes;
+          const char *s;
+          char *quoted_string;
+          char *p;
+
+          length = 0;
+          backslashes = 0;
+          if (quote_around)
+            length++;
+          for (s = string; *s != '\0'; s++)
+            {
+              char c = *s;
+              if (c == '"')
+                length += backslashes + 1;
+              length++;
+              if (c == '\\')
+                backslashes++;
+              else
+                backslashes = 0;
+            }
+          if (quote_around)
+            length += backslashes + 1;
+
+          quoted_string = (char *) malloc (length + 1);
+
+          p = quoted_string;
+          backslashes = 0;
+          if (quote_around)
+            *p++ = '"';
+          for (s = string; *s != '\0'; s++)
+            {
+              char c = *s;
+              if (c == '"')
+                {
+                  unsigned int j;
+                  for (j = backslashes + 1; j > 0; j--)
+                    *p++ = '\\';
+                }
+              *p++ = c;
+              if (c == '\\')
+                backslashes++;
+              else
+                backslashes = 0;
+            }
+          if (quote_around)
+            {
+              unsigned int j;
+              for (j = backslashes; j > 0; j--)
+                *p++ = '\\';
+              *p++ = '"';
+            }
+          *p = '\0';
+
+          new_argv[i] = quoted_string;
+        }
+      else
+        new_argv[i] = strdup (string);
+    }
+
+  new_argv[argc] = NULL;
+
+  return new_argv;
+}
+
+#endif
+
 int
 octave_execv_wrapper (const char *file, char *const *argv)
 {
+#if defined (__WIN32__) && ! defined (__CYGWIN__)
+
+  char **sanitized_argv = prepare_spawn (argv);
+
+  int status = spawnv (P_OVERLAY, file, sanitized_argv);
+
+  // This only happens if spawnv fails.
+
+  char **p = sanitized_argv;
+  while (*p)
+    free (*p++);
+  free (sanitized_argv);
+
+  return status;
+
+#else
+
   return execv (file, argv);
+
+#endif
 }
 
 int
@@ -133,19 +287,31 @@
 gid_t
 octave_getegid_wrapper (void)
 {
+#if defined (HAVE_GETEGID)
   return getegid ();
+#else
+  return -1;
+#endif
 }
 
 uid_t
 octave_geteuid_wrapper (void)
 {
+#if defined (HAVE_GETEUID)
   return geteuid ();
+#else
+  return -1;
+#endif
 }
 
 gid_t
 octave_getgid_wrapper (void)
 {
+#if defined (HAVE_GETGID)
   return getgid ();
+#else
+  return -1;
+#endif
 }
 
 int
@@ -157,25 +323,41 @@
 pid_t
 octave_getpgrp_wrapper (void)
 {
+#if defined (HAVE_GETPGRP)
   return getpgrp ();
+#else
+  return -1;
+#endif
 }
 
 pid_t
 octave_getpid_wrapper (void)
 {
+#if defined (HAVE_GETPID)
   return getpid ();
+#else
+  return -1;
+#endif
 }
 
 pid_t
 octave_getppid_wrapper (void)
 {
+#if defined (HAVE_GETPPID)
   return getppid ();
+#else
+  return -1;
+#endif
 }
 
 uid_t
 octave_getuid_wrapper (void)
 {
+#if defined (HAVE_GETUID)
   return getuid ();
+#else
+  return -1;
+#endif
 }
 
 int
@@ -205,7 +387,11 @@
 pid_t
 octave_setsid_wrapper (void)
 {
+#if defined (HAVE_SETSID)
   return setsid ();
+#else
+  return -1;
+#endif
 }
 
 int
--- a/liboctave/wrappers/unistd-wrappers.h	Fri Jun 17 15:18:58 2016 -0700
+++ b/liboctave/wrappers/unistd-wrappers.h	Sat Jun 18 10:55:49 2016 -0400
@@ -27,6 +27,8 @@
 #  include <stdbool.h>
 #endif
 
+#include <sys/types.h>
+
 #if defined __cplusplus
 extern "C" {
 #endif
--- a/liboctave/wrappers/wait-wrappers.c	Fri Jun 17 15:18:58 2016 -0700
+++ b/liboctave/wrappers/wait-wrappers.c	Sat Jun 18 10:55:49 2016 -0400
@@ -64,6 +64,10 @@
   return WCOREDUMP (status);
 }
 
+#if ! defined (WIFCONTINUED)
+#  define WIFCONTINUED(x) false
+#endif
+
 bool
 octave_wifcontinued_wrapper (int status)
 {
--- a/src/main.in.cc	Fri Jun 17 15:18:58 2016 -0700
+++ b/src/main.in.cc	Sat Jun 18 10:55:49 2016 -0400
@@ -189,137 +189,14 @@
                       : dir;
 }
 
-// Adapted from libtool wrapper.
-#if defined (__WIN32__) && ! defined (__CYGWIN__)
-
-/* Prepares an argument vector before calling spawn().
-   Note that spawn() does not by itself call the command interpreter
-     (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
-      ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-         GetVersionEx(&v);
-         v.dwPlatformId == VER_PLATFORM_WIN32_NT;
-      }) ? "cmd.exe" : "command.com").
-   Instead it simply concatenates the arguments, separated by ' ', and calls
-   CreateProcess().  We must quote the arguments since Win32 CreateProcess()
-   interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
-   special way:
-   - Space and tab are interpreted as delimiters. They are not treated as
-     delimiters if they are surrounded by double quotes: "...".
-   - Unescaped double quotes are removed from the input. Their only effect is
-     that within double quotes, space and tab are treated like normal
-     characters.
-   - Backslashes not followed by double quotes are not special.
-   - But 2*n+1 backslashes followed by a double quote become
-     n backslashes followed by a double quote (n >= 0):
-       \" -> "
-       \\\" -> \"
-       \\\\\" -> \\"
- */
-#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
-#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
-char **
-prepare_spawn (char **argv)
-{
-  size_t argc;
-  char **new_argv;
-  size_t i;
-
-  /* Count number of arguments.  */
-  for (argc = 0; argv[argc] != NULL; argc++)
-    ;
-
-  /* Allocate new argument vector.  */
-  new_argv = new char* [argc + 1];
-
-  /* Put quoted arguments into the new argument vector.  */
-  for (i = 0; i < argc; i++)
-    {
-      const char *string = argv[i];
-
-      if (string[0] == '\0')
-        new_argv[i] = octave_strdup_wrapper ("\"\"");
-      else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
-        {
-          int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
-          size_t length;
-          unsigned int backslashes;
-          const char *s;
-          char *quoted_string;
-          char *p;
-
-          length = 0;
-          backslashes = 0;
-          if (quote_around)
-            length++;
-          for (s = string; *s != '\0'; s++)
-            {
-              char c = *s;
-              if (c == '"')
-                length += backslashes + 1;
-              length++;
-              if (c == '\\')
-                backslashes++;
-              else
-                backslashes = 0;
-            }
-          if (quote_around)
-            length += backslashes + 1;
-
-          quoted_string = new char [length + 1];
-
-          p = quoted_string;
-          backslashes = 0;
-          if (quote_around)
-            *p++ = '"';
-          for (s = string; *s != '\0'; s++)
-            {
-              char c = *s;
-              if (c == '"')
-                {
-                  unsigned int j;
-                  for (j = backslashes + 1; j > 0; j--)
-                    *p++ = '\\';
-                }
-              *p++ = c;
-              if (c == '\\')
-                backslashes++;
-              else
-                backslashes = 0;
-            }
-          if (quote_around)
-            {
-              unsigned int j;
-              for (j = backslashes; j > 0; j--)
-                *p++ = '\\';
-              *p++ = '"';
-            }
-          *p = '\0';
-
-          new_argv[i] = quoted_string;
-        }
-      else
-        new_argv[i] = (char *) string;
-    }
-  new_argv[argc] = NULL;
-
-  return new_argv;
-}
-
-#endif
-
 static int
 octave_exec (const std::string& file, char **argv)
 {
-#if defined (__WIN32__) && ! defined (__CYGWIN__)
-  argv = prepare_spawn (argv);
-  return _spawnv (_P_WAIT, file.c_str (), argv);
-#else
-  octave_execv_wrapper (file.c_str (), argv);
+  int status = octave_execv_wrapper (file.c_str (), argv);
 
-  std::cerr << "octave: failed to exec '" << file << "'" << std::endl;
+  std::cerr << argv[0] << ": failed to exec '" << file << "'" << std::endl;
 
-  return 1;
-#endif
+  return status;
 }
 
 static char *
@@ -508,12 +385,20 @@
         }
     }
   else
-    retval = octave_exec (file, new_argv);
+    {
+      retval = octave_exec (file, new_argv);
+
+      if (retval < 0)
+        std::cerr << argv[0] << ": " << std::strerror (errno) << std::endl;
+    }
 
 #else
 
   retval = octave_exec (file, new_argv);
 
+  if (retval < 0)
+    std::cerr << argv[0] << ": " << std::strerror (errno) << std::endl;
+
 #endif
 
   return retval;