diff options
Diffstat (limited to 'linkers/libiberty/pex-win32.c')
-rw-r--r-- | linkers/libiberty/pex-win32.c | 943 |
1 files changed, 0 insertions, 943 deletions
diff --git a/linkers/libiberty/pex-win32.c b/linkers/libiberty/pex-win32.c deleted file mode 100644 index f1d47c7..0000000 --- a/linkers/libiberty/pex-win32.c +++ /dev/null @@ -1,943 +0,0 @@ -/* Utilities to execute a program in a subprocess (possibly linked by pipes - with other subprocesses), and wait for it. Generic Win32 specialization. - Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. - -This file is part of the libiberty library. -Libiberty is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -Libiberty 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 -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with libiberty; see the file COPYING.LIB. If not, -write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, -Boston, MA 02110-1301, USA. */ - -#include "pex-common.h" - -#include <windows.h> - -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif -#ifdef HAVE_SYS_WAIT_H -#include <sys/wait.h> -#endif - -#include <assert.h> -#include <process.h> -#include <io.h> -#include <fcntl.h> -#include <signal.h> -#include <sys/stat.h> -#include <errno.h> -#include <ctype.h> -#include <malloc.h> - -/* mingw32 headers may not define the following. */ - -#ifndef _P_WAIT -# define _P_WAIT 0 -# define _P_NOWAIT 1 -# define _P_OVERLAY 2 -# define _P_NOWAITO 3 -# define _P_DETACH 4 - -# define WAIT_CHILD 0 -# define WAIT_GRANDCHILD 1 -#endif - -#define MINGW_NAME "Minimalist GNU for Windows" -#define MINGW_NAME_LEN (sizeof(MINGW_NAME) - 1) - -extern char *stpcpy (char *dst, const char *src); - -/* Ensure that the executable pathname uses Win32 backslashes. This - is not necessary on NT, but on W9x, forward slashes causes - failure of spawn* and exec* functions (and probably any function - that calls CreateProcess) *iff* the executable pathname (argv[0]) - is a quoted string. And quoting is necessary in case a pathname - contains embedded white space. You can't win. */ -static void -backslashify (char *s) -{ - while ((s = strchr (s, '/')) != NULL) - *s = '\\'; - return; -} - -static int pex_win32_open_read (struct pex_obj *, const char *, int); -static int pex_win32_open_write (struct pex_obj *, const char *, int); -static pid_t pex_win32_exec_child (struct pex_obj *, int, const char *, - char * const *, char * const *, - int, int, int, int, - const char **, int *); -static int pex_win32_close (struct pex_obj *, int); -static pid_t pex_win32_wait (struct pex_obj *, pid_t, int *, - struct pex_time *, int, const char **, int *); -static int pex_win32_pipe (struct pex_obj *, int *, int); -static FILE *pex_win32_fdopenr (struct pex_obj *, int, int); -static FILE *pex_win32_fdopenw (struct pex_obj *, int, int); - -/* The list of functions we pass to the common routines. */ - -const struct pex_funcs funcs = -{ - pex_win32_open_read, - pex_win32_open_write, - pex_win32_exec_child, - pex_win32_close, - pex_win32_wait, - pex_win32_pipe, - pex_win32_fdopenr, - pex_win32_fdopenw, - NULL /* cleanup */ -}; - -/* Return a newly initialized pex_obj structure. */ - -struct pex_obj * -pex_init (int flags, const char *pname, const char *tempbase) -{ - return pex_init_common (flags, pname, tempbase, &funcs); -} - -/* Open a file for reading. */ - -static int -pex_win32_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, - int binary) -{ - return _open (name, _O_RDONLY | (binary ? _O_BINARY : _O_TEXT)); -} - -/* Open a file for writing. */ - -static int -pex_win32_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, - int binary) -{ - /* Note that we can't use O_EXCL here because gcc may have already - created the temporary file via make_temp_file. */ - return _open (name, - (_O_WRONLY | _O_CREAT | _O_TRUNC - | (binary ? _O_BINARY : _O_TEXT)), - _S_IREAD | _S_IWRITE); -} - -/* Close a file. */ - -static int -pex_win32_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd) -{ - return _close (fd); -} - -#ifdef USE_MINGW_MSYS -static const char *mingw_keys[] = {"SOFTWARE", "Microsoft", "Windows", "CurrentVersion", "Uninstall", NULL}; - -/* Tack the executable on the end of a (possibly slash terminated) buffer - and convert everything to \. */ -static const char * -tack_on_executable (char *buf, const char *executable) -{ - char *p = strchr (buf, '\0'); - if (p > buf && (p[-1] == '\\' || p[-1] == '/')) - p[-1] = '\0'; - backslashify (strcat (buf, executable)); - return buf; -} - -/* Walk down a registry hierarchy until the end. Return the key. */ -static HKEY -openkey (HKEY hStart, const char *keys[]) -{ - HKEY hKey, hTmp; - for (hKey = hStart; *keys; keys++) - { - LONG res; - hTmp = hKey; - res = RegOpenKey (hTmp, *keys, &hKey); - - if (hTmp != HKEY_LOCAL_MACHINE) - RegCloseKey (hTmp); - - if (res != ERROR_SUCCESS) - return NULL; - } - return hKey; -} - -/* Return the "mingw root" as derived from the mingw uninstall information. */ -static const char * -mingw_rootify (const char *executable) -{ - HKEY hKey, hTmp; - DWORD maxlen; - char *namebuf, *foundbuf; - DWORD i; - LONG res; - - /* Open the uninstall "directory". */ - hKey = openkey (HKEY_LOCAL_MACHINE, mingw_keys); - - /* Not found. */ - if (!hKey) - return executable; - - /* Need to enumerate all of the keys here looking for one the most recent - one for MinGW. */ - if (RegQueryInfoKey (hKey, NULL, NULL, NULL, NULL, &maxlen, NULL, NULL, - NULL, NULL, NULL, NULL) != ERROR_SUCCESS) - { - RegCloseKey (hKey); - return executable; - } - namebuf = XNEWVEC (char, ++maxlen); - foundbuf = XNEWVEC (char, maxlen); - foundbuf[0] = '\0'; - if (!namebuf || !foundbuf) - { - RegCloseKey (hKey); - free (namebuf); - free (foundbuf); - return executable; - } - - /* Look through all of the keys for one that begins with Minimal GNU... - Try to get the latest version by doing a string compare although that - string never really works with version number sorting. */ - for (i = 0; RegEnumKey (hKey, i, namebuf, maxlen) == ERROR_SUCCESS; i++) - { - int match = strcasecmp (namebuf, MINGW_NAME); - if (match < 0) - continue; - if (match > 0 && strncasecmp (namebuf, MINGW_NAME, MINGW_NAME_LEN) > 0) - continue; - if (strcasecmp (namebuf, foundbuf) > 0) - strcpy (foundbuf, namebuf); - } - free (namebuf); - - /* If foundbuf is empty, we didn't find anything. Punt. */ - if (!foundbuf[0]) - { - free (foundbuf); - RegCloseKey (hKey); - return executable; - } - - /* Open the key that we wanted */ - res = RegOpenKey (hKey, foundbuf, &hTmp); - RegCloseKey (hKey); - free (foundbuf); - - /* Don't know why this would fail, but you gotta check */ - if (res != ERROR_SUCCESS) - return executable; - - maxlen = 0; - /* Get the length of the value pointed to by InstallLocation */ - if (RegQueryValueEx (hTmp, "InstallLocation", 0, NULL, NULL, - &maxlen) != ERROR_SUCCESS || maxlen == 0) - { - RegCloseKey (hTmp); - return executable; - } - - /* Allocate space for the install location */ - foundbuf = XNEWVEC (char, maxlen + strlen (executable)); - if (!foundbuf) - { - free (foundbuf); - RegCloseKey (hTmp); - } - - /* Read the install location into the buffer */ - res = RegQueryValueEx (hTmp, "InstallLocation", 0, NULL, (LPBYTE) foundbuf, - &maxlen); - RegCloseKey (hTmp); - if (res != ERROR_SUCCESS) - { - free (foundbuf); - return executable; - } - - /* Concatenate the install location and the executable, turn all slashes - to backslashes, and return that. */ - return tack_on_executable (foundbuf, executable); -} - -/* Read the install location of msys from it's installation file and - rootify the executable based on that. */ -static const char * -msys_rootify (const char *executable) -{ - size_t bufsize = 64; - size_t execlen = strlen (executable) + 1; - char *buf; - DWORD res = 0; - for (;;) - { - buf = XNEWVEC (char, bufsize + execlen); - if (!buf) - break; - res = GetPrivateProfileString ("InstallSettings", "InstallPath", NULL, - buf, bufsize, "msys.ini"); - if (!res) - break; - if (strlen (buf) < bufsize) - break; - res = 0; - free (buf); - bufsize *= 2; - if (bufsize > 65536) - { - buf = NULL; - break; - } - } - - if (res) - return tack_on_executable (buf, executable); - - /* failed */ - free (buf); - return executable; -} -#endif - -/* Return the number of arguments in an argv array, not including the null - terminating argument. */ - -static int -argv_to_argc (char *const *argv) -{ - char *const *i = argv; - while (*i) - i++; - return i - argv; -} - -/* Return a Windows command-line from ARGV. It is the caller's - responsibility to free the string returned. */ - -static char * -argv_to_cmdline (char *const *argv) -{ - char *cmdline; - char *p; - size_t cmdline_len; - int i, j, k; - - cmdline_len = 0; - for (i = 0; argv[i]; i++) - { - /* We quote every last argument. This simplifies the problem; - we need only escape embedded double-quotes and immediately - preceeding backslash characters. A sequence of backslach characters - that is not follwed by a double quote character will not be - escaped. */ - for (j = 0; argv[i][j]; j++) - { - if (argv[i][j] == '"') - { - /* Escape preceeding backslashes. */ - for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--) - cmdline_len++; - /* Escape the qote character. */ - cmdline_len++; - } - } - /* Trailing backslashes also need to be escaped because they will be - followed by the terminating quote. */ - for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--) - cmdline_len++; - cmdline_len += j; - cmdline_len += 3; /* for leading and trailing quotes and space */ - } - cmdline = XNEWVEC (char, cmdline_len); - p = cmdline; - for (i = 0; argv[i]; i++) - { - *p++ = '"'; - for (j = 0; argv[i][j]; j++) - { - if (argv[i][j] == '"') - { - for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--) - *p++ = '\\'; - *p++ = '\\'; - } - *p++ = argv[i][j]; - } - for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--) - *p++ = '\\'; - *p++ = '"'; - *p++ = ' '; - } - p[-1] = '\0'; - return cmdline; -} - -/* We'll try the passed filename with all the known standard - extensions, and then without extension. We try no extension - last so that we don't try to run some random extension-less - file that might be hanging around. We try both extension - and no extension so that we don't need any fancy logic - to determine if a file has extension. */ -static const char *const -std_suffixes[] = { - ".com", - ".exe", - ".bat", - ".cmd", - "", - 0 -}; - -/* Returns the full path to PROGRAM. If SEARCH is true, look for - PROGRAM in each directory in PATH. */ - -static char * -find_executable (const char *program, BOOL search) -{ - char *full_executable; - char *e; - size_t fe_len; - const char *path = 0; - const char *const *ext; - const char *p, *q; - size_t proglen = strlen (program); - int has_slash = (strchr (program, '/') || strchr (program, '\\')); - HANDLE h; - - if (has_slash) - search = FALSE; - - if (search) - path = getenv ("PATH"); - if (!path) - path = ""; - - fe_len = 0; - for (p = path; *p; p = q) - { - q = p; - while (*q != ';' && *q != '\0') - q++; - if ((size_t)(q - p) > fe_len) - fe_len = q - p; - if (*q == ';') - q++; - } - fe_len = fe_len + 1 + proglen + 5 /* space for extension */; - full_executable = XNEWVEC (char, fe_len); - - p = path; - do - { - q = p; - while (*q != ';' && *q != '\0') - q++; - - e = full_executable; - memcpy (e, p, q - p); - e += (q - p); - if (q - p) - *e++ = '\\'; - strcpy (e, program); - - if (*q == ';') - q++; - - for (e = full_executable; *e; e++) - if (*e == '/') - *e = '\\'; - - /* At this point, e points to the terminating NUL character for - full_executable. */ - for (ext = std_suffixes; *ext; ext++) - { - /* Remove any current extension. */ - *e = '\0'; - /* Add the new one. */ - strcat (full_executable, *ext); - - /* Attempt to open this file. */ - h = CreateFile (full_executable, GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - if (h != INVALID_HANDLE_VALUE) - goto found; - } - p = q; - } - while (*p); - free (full_executable); - return 0; - - found: - CloseHandle (h); - return full_executable; -} - -/* Low-level process creation function and helper. */ - -static int -env_compare (const void *a_ptr, const void *b_ptr) -{ - const char *a; - const char *b; - unsigned char c1; - unsigned char c2; - - a = *(const char **) a_ptr; - b = *(const char **) b_ptr; - - /* a and b will be of the form: VAR=VALUE - We compare only the variable name part here using a case-insensitive - comparison algorithm. It might appear that in fact strcasecmp () can - take the place of this whole function, and indeed it could, save for - the fact that it would fail in cases such as comparing A1=foo and - A=bar (because 1 is less than = in the ASCII character set). - (Environment variables containing no numbers would work in such a - scenario.) */ - - do - { - c1 = (unsigned char) tolower (*a++); - c2 = (unsigned char) tolower (*b++); - - if (c1 == '=') - c1 = '\0'; - - if (c2 == '=') - c2 = '\0'; - } - while (c1 == c2 && c1 != '\0'); - - return c1 - c2; -} - -/* Execute a Windows executable as a child process. This will fail if the - * target is not actually an executable, such as if it is a shell script. */ - -static pid_t -win32_spawn (const char *executable, - BOOL search, - char *const *argv, - char *const *env, /* array of strings of the form: VAR=VALUE */ - DWORD dwCreationFlags, - LPSTARTUPINFO si, - LPPROCESS_INFORMATION pi) -{ - char *full_executable; - char *cmdline; - char **env_copy; - char *env_block = NULL; - - full_executable = NULL; - cmdline = NULL; - - if (env) - { - int env_size; - - /* Count the number of environment bindings supplied. */ - for (env_size = 0; env[env_size]; env_size++) - continue; - - /* Assemble an environment block, if required. This consists of - VAR=VALUE strings juxtaposed (with one null character between each - pair) and an additional null at the end. */ - if (env_size > 0) - { - int var; - int total_size = 1; /* 1 is for the final null. */ - char *bufptr; - - /* Windows needs the members of the block to be sorted by variable - name. */ - env_copy = (char **) alloca (sizeof (char *) * env_size); - memcpy (env_copy, env, sizeof (char *) * env_size); - qsort (env_copy, env_size, sizeof (char *), env_compare); - - for (var = 0; var < env_size; var++) - total_size += strlen (env[var]) + 1; - - env_block = XNEWVEC (char, total_size); - bufptr = env_block; - for (var = 0; var < env_size; var++) - bufptr = stpcpy (bufptr, env_copy[var]) + 1; - - *bufptr = '\0'; - } - } - - full_executable = find_executable (executable, search); - if (!full_executable) - goto error; - cmdline = argv_to_cmdline (argv); - if (!cmdline) - goto error; - - /* Create the child process. */ - if (!CreateProcess (full_executable, cmdline, - /*lpProcessAttributes=*/NULL, - /*lpThreadAttributes=*/NULL, - /*bInheritHandles=*/TRUE, - dwCreationFlags, - (LPVOID) env_block, - /*lpCurrentDirectory=*/NULL, - si, - pi)) - { - free (env_block); - - free (full_executable); - - return (pid_t) -1; - } - - /* Clean up. */ - CloseHandle (pi->hThread); - free (full_executable); - free (env_block); - - return (pid_t) pi->hProcess; - - error: - free (env_block); - free (cmdline); - free (full_executable); - - return (pid_t) -1; -} - -/* Spawn a script. This simulates the Unix script execution mechanism. - This function is called as a fallback if win32_spawn fails. */ - -static pid_t -spawn_script (const char *executable, char *const *argv, - char* const *env, - DWORD dwCreationFlags, - LPSTARTUPINFO si, - LPPROCESS_INFORMATION pi) -{ - pid_t pid = (pid_t) -1; - int save_errno = errno; - int fd = _open (executable, _O_RDONLY); - - /* Try to open script, check header format, extract interpreter path, - and spawn script using that interpretter. */ - if (fd >= 0) - { - char buf[MAX_PATH + 5]; - int len = _read (fd, buf, sizeof (buf) - 1); - _close (fd); - if (len > 3) - { - char *eol; - buf[len] = '\0'; - eol = strchr (buf, '\n'); - if (eol && strncmp (buf, "#!", 2) == 0) - { - - /* Header format is OK. */ - char *executable1; - int new_argc; - const char **avhere; - - /* Extract interpreter path. */ - do - *eol = '\0'; - while (*--eol == '\r' || *eol == ' ' || *eol == '\t'); - for (executable1 = buf + 2; *executable1 == ' ' || *executable1 == '\t'; executable1++) - continue; - backslashify (executable1); - - /* Duplicate argv, prepending the interpreter path. */ - new_argc = argv_to_argc (argv) + 1; - avhere = XNEWVEC (const char *, new_argc + 1); - *avhere = executable1; - memcpy (avhere + 1, argv, new_argc * sizeof(*argv)); - argv = (char *const *)avhere; - - /* Spawn the child. */ -#ifndef USE_MINGW_MSYS - executable = strrchr (executable1, '\\') + 1; - if (!executable) - executable = executable1; - pid = win32_spawn (executable, TRUE, argv, env, - dwCreationFlags, si, pi); -#else - if (strchr (executable1, '\\') == NULL) - pid = win32_spawn (executable1, TRUE, argv, env, - dwCreationFlags, si, pi); - else if (executable1[0] != '\\') - pid = win32_spawn (executable1, FALSE, argv, env, - dwCreationFlags, si, pi); - else - { - const char *newex = mingw_rootify (executable1); - *avhere = newex; - pid = win32_spawn (newex, FALSE, argv, env, - dwCreationFlags, si, pi); - if (executable1 != newex) - free ((char *) newex); - if (pid == (pid_t) -1) - { - newex = msys_rootify (executable1); - if (newex != executable1) - { - *avhere = newex; - pid = win32_spawn (newex, FALSE, argv, env, - dwCreationFlags, si, pi); - free ((char *) newex); - } - } - } -#endif - free (avhere); - } - } - } - if (pid == (pid_t) -1) - errno = save_errno; - return pid; -} - -/* Execute a child. */ - -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) -{ - DWORD termstat; - HANDLE h; - - if (time != NULL) - memset (time, 0, sizeof *time); - - h = (HANDLE) pid; - - /* FIXME: If done is non-zero, we should probably try to kill the - process. */ - if (WaitForSingleObject (h, INFINITE) != WAIT_OBJECT_0) - { - CloseHandle (h); - *err = ECHILD; - *errmsg = "WaitForSingleObject"; - return -1; - } - - GetExitCodeProcess (h, &termstat); - CloseHandle (h); - - /* A value of 3 indicates that the child caught a signal, but not - which one. Since only SIGABRT, SIGFPE and SIGINT do anything, we - report SIGABRT. */ - if (termstat == 3) - *status = SIGABRT; - else - *status = (termstat & 0xff) << 8; - - return 0; -} - -/* Create a pipe. */ - -static int -pex_win32_pipe (struct pex_obj *obj ATTRIBUTE_UNUSED, int *p, - int binary) -{ - return _pipe (p, 256, (binary ? _O_BINARY : _O_TEXT) | _O_NOINHERIT); -} - -/* Get a FILE pointer to read from a file descriptor. */ - -static FILE * -pex_win32_fdopenr (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd, - int binary) -{ - HANDLE h = (HANDLE) _get_osfhandle (fd); - if (h == INVALID_HANDLE_VALUE) - return NULL; - if (! SetHandleInformation (h, HANDLE_FLAG_INHERIT, 0)) - return NULL; - return fdopen (fd, binary ? "rb" : "r"); -} - -static FILE * -pex_win32_fdopenw (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd, - int binary) -{ - HANDLE h = (HANDLE) _get_osfhandle (fd); - if (h == INVALID_HANDLE_VALUE) - return NULL; - if (! SetHandleInformation (h, HANDLE_FLAG_INHERIT, 0)) - return NULL; - return fdopen (fd, binary ? "wb" : "w"); -} - -#ifdef MAIN -#include <stdio.h> - -int -main (int argc ATTRIBUTE_UNUSED, char **argv) -{ - char const *errmsg; - int err; - argv++; - printf ("%ld\n", (long) pex_win32_exec_child (NULL, PEX_SEARCH, argv[0], argv, NULL, 0, 0, 1, 2, &errmsg, &err)); - exit (0); -} -#endif |