+static pid_t
+pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags,
+ const char *executable, char * const * argv,
+ char* const* env,
+ int in, int out, int errdes,
+ int toclose ATTRIBUTE_UNUSED,
+ const char **errmsg,
+ int *err)
+{
+ pid_t pid;
+ HANDLE stdin_handle;
+ HANDLE stdout_handle;
+ HANDLE stderr_handle;
+ DWORD dwCreationFlags;
+ OSVERSIONINFO version_info;
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ int orig_out, orig_in, orig_err;
+ BOOL separate_stderr = !(flags & PEX_STDERR_TO_STDOUT);
+
+ /* Ensure we have inheritable descriptors to pass to the child, and close the
+ original descriptors. */
+ orig_in = in;
+ in = _dup (orig_in);
+ if (orig_in != STDIN_FILENO)
+ _close (orig_in);
+
+ orig_out = out;
+ out = _dup (orig_out);
+ if (orig_out != STDOUT_FILENO)
+ _close (orig_out);
+
+ if (separate_stderr)
+ {
+ orig_err = errdes;
+ errdes = _dup (orig_err);
+ if (orig_err != STDERR_FILENO)
+ _close (orig_err);
+ }
+
+ stdin_handle = INVALID_HANDLE_VALUE;
+ stdout_handle = INVALID_HANDLE_VALUE;
+ stderr_handle = INVALID_HANDLE_VALUE;
+
+ stdin_handle = (HANDLE) _get_osfhandle (in);
+ stdout_handle = (HANDLE) _get_osfhandle (out);
+ if (separate_stderr)
+ stderr_handle = (HANDLE) _get_osfhandle (errdes);
+ else
+ stderr_handle = stdout_handle;
+
+ /* Determine the version of Windows we are running on. */
+ version_info.dwOSVersionInfoSize = sizeof (version_info);
+ GetVersionEx (&version_info);
+ if (version_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
+ /* On Windows 95/98/ME the CREATE_NO_WINDOW flag is not
+ supported, so we cannot avoid creating a console window. */
+ dwCreationFlags = 0;
+ else
+ {
+ HANDLE conout_handle;
+
+ /* Determine whether or not we have an associated console. */
+ conout_handle = CreateFile("CONOUT$",
+ GENERIC_WRITE,
+ FILE_SHARE_WRITE,
+ /*lpSecurityAttributes=*/NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ /*hTemplateFile=*/NULL);
+ if (conout_handle == INVALID_HANDLE_VALUE)
+ /* There is no console associated with this process. Since
+ the child is a console process, the OS would normally
+ create a new console Window for the child. Since we'll be
+ redirecting the child's standard streams, we do not need
+ the console window. */
+ dwCreationFlags = CREATE_NO_WINDOW;
+ else
+ {
+ /* There is a console associated with the process, so the OS
+ will not create a new console. And, if we use
+ CREATE_NO_WINDOW in this situation, the child will have
+ no associated console. Therefore, if the child's
+ standard streams are connected to the console, the output
+ will be discarded. */
+ CloseHandle(conout_handle);
+ dwCreationFlags = 0;
+ }
+ }
+
+ /* Since the child will be a console process, it will, by default,
+ connect standard input/output to its console. However, we want
+ the child to use the handles specifically designated above. In
+ addition, if there is no console (such as when we are running in
+ a Cygwin X window), then we must redirect the child's
+ input/output, as there is no console for the child to use. */
+ memset (&si, 0, sizeof (si));
+ si.cb = sizeof (si);
+ si.dwFlags = STARTF_USESTDHANDLES;
+ si.hStdInput = stdin_handle;
+ si.hStdOutput = stdout_handle;
+ si.hStdError = stderr_handle;
+
+ /* Create the child process. */
+ pid = win32_spawn (executable, (flags & PEX_SEARCH) != 0,
+ argv, env, dwCreationFlags, &si, &pi);
+ if (pid == (pid_t) -1)
+ pid = spawn_script (executable, argv, env, dwCreationFlags,
+ &si, &pi);
+ if (pid == (pid_t) -1)
+ {
+ *err = ENOENT;
+ *errmsg = "CreateProcess";
+ }
+
+ /* Close the standard input, standard output and standard error handles
+ in the parent. */
+
+ _close (in);
+ _close (out);
+ if (separate_stderr)
+ _close (errdes);
+
+ return pid;
+}
+
+/* Wait for a child process to complete. MS CRTDLL doesn't return
+ enough information in status to decide if the child exited due to a
+ signal or not, rather it simply returns an integer with the exit
+ code of the child; eg., if the child exited with an abort() call
+ and didn't have a handler for SIGABRT, it simply returns with
+ status == 3. We fix the status code to conform to the usual WIF*
+ macros. Note that WIFSIGNALED will never be true under CRTDLL. */
+
+static pid_t
+pex_win32_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid,
+ int *status, struct pex_time *time, int done ATTRIBUTE_UNUSED,
+ const char **errmsg, int *err)