Home | History | Annotate | Download | only in libiberty
      1 /* Utilities to execute a program in a subprocess (possibly linked by pipes
      2    with other subprocesses), and wait for it.  Generic Win32 specialization.
      3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006
      4    Free Software Foundation, Inc.
      5 
      6 This file is part of the libiberty library.
      7 Libiberty is free software; you can redistribute it and/or
      8 modify it under the terms of the GNU Library General Public
      9 License as published by the Free Software Foundation; either
     10 version 2 of the License, or (at your option) any later version.
     11 
     12 Libiberty is distributed in the hope that it will be useful,
     13 but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15 Library General Public License for more details.
     16 
     17 You should have received a copy of the GNU Library General Public
     18 License along with libiberty; see the file COPYING.LIB.  If not,
     19 write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
     20 Boston, MA 02110-1301, USA.  */
     21 
     22 #include "pex-common.h"
     23 
     24 #include <windows.h>
     25 
     26 #ifdef HAVE_STDLIB_H
     27 #include <stdlib.h>
     28 #endif
     29 #ifdef HAVE_STRING_H
     30 #include <string.h>
     31 #endif
     32 #ifdef HAVE_UNISTD_H
     33 #include <unistd.h>
     34 #endif
     35 #ifdef HAVE_SYS_WAIT_H
     36 #include <sys/wait.h>
     37 #endif
     38 
     39 #include <assert.h>
     40 #include <process.h>
     41 #include <io.h>
     42 #include <fcntl.h>
     43 #include <signal.h>
     44 #include <sys/stat.h>
     45 #include <errno.h>
     46 #include <ctype.h>
     47 
     48 /* mingw32 headers may not define the following.  */
     49 
     50 #ifndef _P_WAIT
     51 #  define _P_WAIT	0
     52 #  define _P_NOWAIT	1
     53 #  define _P_OVERLAY	2
     54 #  define _P_NOWAITO	3
     55 #  define _P_DETACH	4
     56 
     57 #  define WAIT_CHILD		0
     58 #  define WAIT_GRANDCHILD	1
     59 #endif
     60 
     61 #define MINGW_NAME "Minimalist GNU for Windows"
     62 #define MINGW_NAME_LEN (sizeof(MINGW_NAME) - 1)
     63 
     64 extern char *stpcpy (char *dst, const char *src);
     65 
     66 /* Ensure that the executable pathname uses Win32 backslashes. This
     67    is not necessary on NT, but on W9x, forward slashes causes
     68    failure of spawn* and exec* functions (and probably any function
     69    that calls CreateProcess) *iff* the executable pathname (argv[0])
     70    is a quoted string.  And quoting is necessary in case a pathname
     71    contains embedded white space.  You can't win.  */
     72 static void
     73 backslashify (char *s)
     74 {
     75   while ((s = strchr (s, '/')) != NULL)
     76     *s = '\\';
     77   return;
     78 }
     79 
     80 static int pex_win32_open_read (struct pex_obj *, const char *, int);
     81 static int pex_win32_open_write (struct pex_obj *, const char *, int, int);
     82 static pid_t pex_win32_exec_child (struct pex_obj *, int, const char *,
     83 				  char * const *, char * const *,
     84                                   int, int, int, int,
     85 				  const char **, int *);
     86 static int pex_win32_close (struct pex_obj *, int);
     87 static pid_t pex_win32_wait (struct pex_obj *, pid_t, int *,
     88 			   struct pex_time *, int, const char **, int *);
     89 static int pex_win32_pipe (struct pex_obj *, int *, int);
     90 static FILE *pex_win32_fdopenr (struct pex_obj *, int, int);
     91 static FILE *pex_win32_fdopenw (struct pex_obj *, int, int);
     92 
     93 /* The list of functions we pass to the common routines.  */
     94 
     95 const struct pex_funcs funcs =
     96 {
     97   pex_win32_open_read,
     98   pex_win32_open_write,
     99   pex_win32_exec_child,
    100   pex_win32_close,
    101   pex_win32_wait,
    102   pex_win32_pipe,
    103   pex_win32_fdopenr,
    104   pex_win32_fdopenw,
    105   NULL /* cleanup */
    106 };
    107 
    108 /* Return a newly initialized pex_obj structure.  */
    109 
    110 struct pex_obj *
    111 pex_init (int flags, const char *pname, const char *tempbase)
    112 {
    113   return pex_init_common (flags, pname, tempbase, &funcs);
    114 }
    115 
    116 /* Open a file for reading.  */
    117 
    118 static int
    119 pex_win32_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
    120 		     int binary)
    121 {
    122   return _open (name, _O_RDONLY | (binary ? _O_BINARY : _O_TEXT));
    123 }
    124 
    125 /* Open a file for writing.  */
    126 
    127 static int
    128 pex_win32_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
    129 		      int binary, int append)
    130 {
    131   /* Note that we can't use O_EXCL here because gcc may have already
    132      created the temporary file via make_temp_file.  */
    133   if (append)
    134     return -1;
    135   return _open (name,
    136 		(_O_WRONLY | _O_CREAT | _O_TRUNC
    137 		 | (binary ? _O_BINARY : _O_TEXT)),
    138 		_S_IREAD | _S_IWRITE);
    139 }
    140 
    141 /* Close a file.  */
    142 
    143 static int
    144 pex_win32_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd)
    145 {
    146   return _close (fd);
    147 }
    148 
    149 #ifdef USE_MINGW_MSYS
    150 static const char *mingw_keys[] = {"SOFTWARE", "Microsoft", "Windows", "CurrentVersion", "Uninstall", NULL};
    151 
    152 /* Tack the executable on the end of a (possibly slash terminated) buffer
    153    and convert everything to \. */
    154 static const char *
    155 tack_on_executable (char *buf, const char *executable)
    156 {
    157   char *p = strchr (buf, '\0');
    158   if (p > buf && (p[-1] == '\\' || p[-1] == '/'))
    159     p[-1] = '\0';
    160   backslashify (strcat (buf, executable));
    161   return buf;
    162 }
    163 
    164 /* Walk down a registry hierarchy until the end.  Return the key. */
    165 static HKEY
    166 openkey (HKEY hStart, const char *keys[])
    167 {
    168   HKEY hKey, hTmp;
    169   for (hKey = hStart; *keys; keys++)
    170     {
    171       LONG res;
    172       hTmp = hKey;
    173       res = RegOpenKey (hTmp, *keys, &hKey);
    174 
    175       if (hTmp != HKEY_LOCAL_MACHINE)
    176 	RegCloseKey (hTmp);
    177 
    178       if (res != ERROR_SUCCESS)
    179 	return NULL;
    180     }
    181   return hKey;
    182 }
    183 
    184 /* Return the "mingw root" as derived from the mingw uninstall information. */
    185 static const char *
    186 mingw_rootify (const char *executable)
    187 {
    188   HKEY hKey, hTmp;
    189   DWORD maxlen;
    190   char *namebuf, *foundbuf;
    191   DWORD i;
    192   LONG res;
    193 
    194   /* Open the uninstall "directory". */
    195   hKey = openkey (HKEY_LOCAL_MACHINE, mingw_keys);
    196 
    197   /* Not found. */
    198   if (!hKey)
    199     return executable;
    200 
    201   /* Need to enumerate all of the keys here looking for one the most recent
    202      one for MinGW. */
    203   if (RegQueryInfoKey (hKey, NULL, NULL, NULL, NULL, &maxlen, NULL, NULL,
    204 		       NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
    205     {
    206       RegCloseKey (hKey);
    207       return executable;
    208     }
    209   namebuf = XNEWVEC (char, ++maxlen);
    210   foundbuf = XNEWVEC (char, maxlen);
    211   foundbuf[0] = '\0';
    212   if (!namebuf || !foundbuf)
    213     {
    214       RegCloseKey (hKey);
    215       free (namebuf);
    216       free (foundbuf);
    217       return executable;
    218     }
    219 
    220   /* Look through all of the keys for one that begins with Minimal GNU...
    221      Try to get the latest version by doing a string compare although that
    222      string never really works with version number sorting. */
    223   for (i = 0; RegEnumKey (hKey, i, namebuf, maxlen) == ERROR_SUCCESS; i++)
    224     {
    225       int match = strcasecmp (namebuf, MINGW_NAME);
    226       if (match < 0)
    227 	continue;
    228       if (match > 0 && strncasecmp (namebuf, MINGW_NAME, MINGW_NAME_LEN) > 0)
    229 	continue;
    230       if (strcasecmp (namebuf, foundbuf) > 0)
    231 	strcpy (foundbuf, namebuf);
    232     }
    233   free (namebuf);
    234 
    235   /* If foundbuf is empty, we didn't find anything.  Punt. */
    236   if (!foundbuf[0])
    237     {
    238       free (foundbuf);
    239       RegCloseKey (hKey);
    240       return executable;
    241     }
    242 
    243   /* Open the key that we wanted */
    244   res = RegOpenKey (hKey, foundbuf, &hTmp);
    245   RegCloseKey (hKey);
    246   free (foundbuf);
    247 
    248   /* Don't know why this would fail, but you gotta check */
    249   if (res != ERROR_SUCCESS)
    250     return executable;
    251 
    252   maxlen = 0;
    253   /* Get the length of the value pointed to by InstallLocation */
    254   if (RegQueryValueEx (hTmp, "InstallLocation", 0, NULL, NULL,
    255 		       &maxlen) != ERROR_SUCCESS || maxlen == 0)
    256     {
    257       RegCloseKey (hTmp);
    258       return executable;
    259     }
    260 
    261   /* Allocate space for the install location */
    262   foundbuf = XNEWVEC (char, maxlen + strlen (executable));
    263   if (!foundbuf)
    264     {
    265       free (foundbuf);
    266       RegCloseKey (hTmp);
    267     }
    268 
    269   /* Read the install location into the buffer */
    270   res = RegQueryValueEx (hTmp, "InstallLocation", 0, NULL, (LPBYTE) foundbuf,
    271 			 &maxlen);
    272   RegCloseKey (hTmp);
    273   if (res != ERROR_SUCCESS)
    274     {
    275       free (foundbuf);
    276       return executable;
    277     }
    278 
    279   /* Concatenate the install location and the executable, turn all slashes
    280      to backslashes, and return that. */
    281   return tack_on_executable (foundbuf, executable);
    282 }
    283 
    284 /* Read the install location of msys from it's installation file and
    285    rootify the executable based on that. */
    286 static const char *
    287 msys_rootify (const char *executable)
    288 {
    289   size_t bufsize = 64;
    290   size_t execlen = strlen (executable) + 1;
    291   char *buf;
    292   DWORD res = 0;
    293   for (;;)
    294     {
    295       buf = XNEWVEC (char, bufsize + execlen);
    296       if (!buf)
    297 	break;
    298       res = GetPrivateProfileString ("InstallSettings", "InstallPath", NULL,
    299 				     buf, bufsize, "msys.ini");
    300       if (!res)
    301 	break;
    302       if (strlen (buf) < bufsize)
    303 	break;
    304       res = 0;
    305       free (buf);
    306       bufsize *= 2;
    307       if (bufsize > 65536)
    308 	{
    309 	  buf = NULL;
    310 	  break;
    311 	}
    312     }
    313 
    314   if (res)
    315     return tack_on_executable (buf, executable);
    316 
    317   /* failed */
    318   free (buf);
    319   return executable;
    320 }
    321 #endif
    322 
    323 /* Return the number of arguments in an argv array, not including the null
    324    terminating argument. */
    325 
    326 static int
    327 argv_to_argc (char *const *argv)
    328 {
    329   char *const *i = argv;
    330   while (*i)
    331     i++;
    332   return i - argv;
    333 }
    334 
    335 /* Return a Windows command-line from ARGV.  It is the caller's
    336    responsibility to free the string returned.  */
    337 
    338 static char *
    339 argv_to_cmdline (char *const *argv)
    340 {
    341   char *cmdline;
    342   char *p;
    343   size_t cmdline_len;
    344   int i, j, k;
    345   int needs_quotes;
    346 
    347   cmdline_len = 0;
    348   for (i = 0; argv[i]; i++)
    349     {
    350       /* We only quote arguments that contain spaces, \t or " characters to
    351 	 prevent wasting 2 chars per argument of the CreateProcess 32k char
    352 	 limit.  We need only escape embedded double-quotes and immediately
    353 	 preceeding backslash characters.  A sequence of backslach characters
    354 	 that is not follwed by a double quote character will not be
    355 	 escaped.  */
    356       needs_quotes = 0;
    357       for (j = 0; argv[i][j]; j++)
    358 	{
    359 	  if (argv[i][j] == ' ' || argv[i][j] == '\t' || argv[i][j] == '"')
    360 	    {
    361 	      needs_quotes = 1;
    362 	    }
    363 
    364 	  if (argv[i][j] == '"')
    365 	    {
    366 	      /* Escape preceeding backslashes.  */
    367 	      for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
    368 		cmdline_len++;
    369 	      /* Escape the qote character.  */
    370 	      cmdline_len++;
    371 	    }
    372 	}
    373       /* Trailing backslashes also need to be escaped because they will be
    374          followed by the terminating quote.  */
    375       if (needs_quotes)
    376         {
    377           for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
    378             cmdline_len++;
    379         }
    380       cmdline_len += j;
    381       /* for leading and trailing quotes and space */
    382       cmdline_len += needs_quotes * 2 + 1;
    383     }
    384   cmdline = XNEWVEC (char, cmdline_len);
    385   p = cmdline;
    386   for (i = 0; argv[i]; i++)
    387     {
    388       needs_quotes = 0;
    389       for (j = 0; argv[i][j]; j++)
    390         {
    391           if (argv[i][j] == ' ' || argv[i][j] == '\t' || argv[i][j] == '"')
    392             {
    393               needs_quotes = 1;
    394               break;
    395             }
    396         }
    397 
    398       if (needs_quotes)
    399         {
    400           *p++ = '"';
    401         }
    402       for (j = 0; argv[i][j]; j++)
    403 	{
    404 	  if (argv[i][j] == '"')
    405 	    {
    406 	      for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
    407 		*p++ = '\\';
    408 	      *p++ = '\\';
    409 	    }
    410 	  *p++ = argv[i][j];
    411 	}
    412       if (needs_quotes)
    413         {
    414           for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
    415             *p++ = '\\';
    416           *p++ = '"';
    417         }
    418       *p++ = ' ';
    419     }
    420   p[-1] = '\0';
    421   return cmdline;
    422 }
    423 
    424 /* We'll try the passed filename with all the known standard
    425    extensions, and then without extension.  We try no extension
    426    last so that we don't try to run some random extension-less
    427    file that might be hanging around.  We try both extension
    428    and no extension so that we don't need any fancy logic
    429    to determine if a file has extension.  */
    430 static const char *const
    431 std_suffixes[] = {
    432   ".com",
    433   ".exe",
    434   ".bat",
    435   ".cmd",
    436   "",
    437   0
    438 };
    439 
    440 /* Returns the full path to PROGRAM.  If SEARCH is true, look for
    441    PROGRAM in each directory in PATH.  */
    442 
    443 static char *
    444 find_executable (const char *program, BOOL search)
    445 {
    446   char *full_executable;
    447   char *e;
    448   size_t fe_len;
    449   const char *path = 0;
    450   const char *const *ext;
    451   const char *p, *q;
    452   size_t proglen = strlen (program);
    453   int has_slash = (strchr (program, '/') || strchr (program, '\\'));
    454   HANDLE h;
    455 
    456   if (has_slash)
    457     search = FALSE;
    458 
    459   if (search)
    460     path = getenv ("PATH");
    461   if (!path)
    462     path = "";
    463 
    464   fe_len = 0;
    465   for (p = path; *p; p = q)
    466     {
    467       q = p;
    468       while (*q != ';' && *q != '\0')
    469 	q++;
    470       if ((size_t)(q - p) > fe_len)
    471 	fe_len = q - p;
    472       if (*q == ';')
    473 	q++;
    474     }
    475   fe_len = fe_len + 1 + proglen + 5 /* space for extension */;
    476   full_executable = XNEWVEC (char, fe_len);
    477 
    478   p = path;
    479   do
    480     {
    481       q = p;
    482       while (*q != ';' && *q != '\0')
    483 	q++;
    484 
    485       e = full_executable;
    486       memcpy (e, p, q - p);
    487       e += (q - p);
    488       if (q - p)
    489 	*e++ = '\\';
    490       strcpy (e, program);
    491 
    492       if (*q == ';')
    493 	q++;
    494 
    495       for (e = full_executable; *e; e++)
    496 	if (*e == '/')
    497 	  *e = '\\';
    498 
    499       /* At this point, e points to the terminating NUL character for
    500          full_executable.  */
    501       for (ext = std_suffixes; *ext; ext++)
    502 	{
    503 	  /* Remove any current extension.  */
    504 	  *e = '\0';
    505 	  /* Add the new one.  */
    506 	  strcat (full_executable, *ext);
    507 
    508 	  /* Attempt to open this file.  */
    509 	  h = CreateFile (full_executable, GENERIC_READ,
    510 			  FILE_SHARE_READ | FILE_SHARE_WRITE,
    511 			  0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    512 	  if (h != INVALID_HANDLE_VALUE)
    513 	    goto found;
    514 	}
    515       p = q;
    516     }
    517   while (*p);
    518   free (full_executable);
    519   return 0;
    520 
    521  found:
    522   CloseHandle (h);
    523   return full_executable;
    524 }
    525 
    526 /* Low-level process creation function and helper.  */
    527 
    528 static int
    529 env_compare (const void *a_ptr, const void *b_ptr)
    530 {
    531   const char *a;
    532   const char *b;
    533   unsigned char c1;
    534   unsigned char c2;
    535 
    536   a = *(const char **) a_ptr;
    537   b = *(const char **) b_ptr;
    538 
    539   /* a and b will be of the form: VAR=VALUE
    540      We compare only the variable name part here using a case-insensitive
    541      comparison algorithm.  It might appear that in fact strcasecmp () can
    542      take the place of this whole function, and indeed it could, save for
    543      the fact that it would fail in cases such as comparing A1=foo and
    544      A=bar (because 1 is less than = in the ASCII character set).
    545      (Environment variables containing no numbers would work in such a
    546      scenario.)  */
    547 
    548   do
    549     {
    550       c1 = (unsigned char) tolower (*a++);
    551       c2 = (unsigned char) tolower (*b++);
    552 
    553       if (c1 == '=')
    554         c1 = '\0';
    555 
    556       if (c2 == '=')
    557         c2 = '\0';
    558     }
    559   while (c1 == c2 && c1 != '\0');
    560 
    561   return c1 - c2;
    562 }
    563 
    564 /* Execute a Windows executable as a child process.  This will fail if the
    565  * target is not actually an executable, such as if it is a shell script. */
    566 
    567 static pid_t
    568 win32_spawn (const char *executable,
    569 	     BOOL search,
    570 	     char *const *argv,
    571              char *const *env, /* array of strings of the form: VAR=VALUE */
    572 	     DWORD dwCreationFlags,
    573 	     LPSTARTUPINFO si,
    574 	     LPPROCESS_INFORMATION pi)
    575 {
    576   char *full_executable;
    577   char *cmdline;
    578   char **env_copy;
    579   char *env_block = NULL;
    580 
    581   full_executable = NULL;
    582   cmdline = NULL;
    583 
    584   if (env)
    585     {
    586       int env_size;
    587 
    588       /* Count the number of environment bindings supplied.  */
    589       for (env_size = 0; env[env_size]; env_size++)
    590         continue;
    591 
    592       /* Assemble an environment block, if required.  This consists of
    593          VAR=VALUE strings juxtaposed (with one null character between each
    594          pair) and an additional null at the end.  */
    595       if (env_size > 0)
    596         {
    597           int var;
    598           int total_size = 1; /* 1 is for the final null.  */
    599           char *bufptr;
    600 
    601           /* Windows needs the members of the block to be sorted by variable
    602              name.  */
    603           env_copy = (char **) alloca (sizeof (char *) * env_size);
    604           memcpy (env_copy, env, sizeof (char *) * env_size);
    605           qsort (env_copy, env_size, sizeof (char *), env_compare);
    606 
    607           for (var = 0; var < env_size; var++)
    608             total_size += strlen (env[var]) + 1;
    609 
    610           env_block = XNEWVEC (char, total_size);
    611           bufptr = env_block;
    612           for (var = 0; var < env_size; var++)
    613             bufptr = stpcpy (bufptr, env_copy[var]) + 1;
    614 
    615           *bufptr = '\0';
    616         }
    617     }
    618 
    619   full_executable = find_executable (executable, search);
    620   if (!full_executable)
    621     goto error;
    622   cmdline = argv_to_cmdline (argv);
    623   if (!cmdline)
    624     goto error;
    625 
    626   /* Create the child process.  */
    627   if (!CreateProcess (full_executable, cmdline,
    628 		      /*lpProcessAttributes=*/NULL,
    629 		      /*lpThreadAttributes=*/NULL,
    630 		      /*bInheritHandles=*/TRUE,
    631 		      dwCreationFlags,
    632 		      (LPVOID) env_block,
    633 		      /*lpCurrentDirectory=*/NULL,
    634 		      si,
    635 		      pi))
    636     {
    637       free (env_block);
    638 
    639       free (full_executable);
    640 
    641       return (pid_t) -1;
    642     }
    643 
    644   /* Clean up.  */
    645   CloseHandle (pi->hThread);
    646   free (full_executable);
    647   free (env_block);
    648 
    649   return (pid_t) pi->hProcess;
    650 
    651  error:
    652   free (env_block);
    653   free (cmdline);
    654   free (full_executable);
    655 
    656   return (pid_t) -1;
    657 }
    658 
    659 /* Spawn a script.  This simulates the Unix script execution mechanism.
    660    This function is called as a fallback if win32_spawn fails. */
    661 
    662 static pid_t
    663 spawn_script (const char *executable, char *const *argv,
    664               char* const *env,
    665 	      DWORD dwCreationFlags,
    666 	      LPSTARTUPINFO si,
    667 	      LPPROCESS_INFORMATION pi)
    668 {
    669   pid_t pid = (pid_t) -1;
    670   int save_errno = errno;
    671   int fd = _open (executable, _O_RDONLY);
    672 
    673   /* Try to open script, check header format, extract interpreter path,
    674      and spawn script using that interpretter. */
    675   if (fd >= 0)
    676     {
    677       char buf[MAX_PATH + 5];
    678       int len = _read (fd, buf, sizeof (buf) - 1);
    679       _close (fd);
    680       if (len > 3)
    681 	{
    682 	  char *eol;
    683 	  buf[len] = '\0';
    684 	  eol = strchr (buf, '\n');
    685 	  if (eol && strncmp (buf, "#!", 2) == 0)
    686 	    {
    687 
    688 	      /* Header format is OK. */
    689 	      char *executable1;
    690               int new_argc;
    691               const char **avhere;
    692 
    693 	      /* Extract interpreter path. */
    694 	      do
    695 		*eol = '\0';
    696 	      while (*--eol == '\r' || *eol == ' ' || *eol == '\t');
    697 	      for (executable1 = buf + 2; *executable1 == ' ' || *executable1 == '\t'; executable1++)
    698 		continue;
    699 	      backslashify (executable1);
    700 
    701 	      /* Duplicate argv, prepending the interpreter path. */
    702 	      new_argc = argv_to_argc (argv) + 1;
    703 	      avhere = XNEWVEC (const char *, new_argc + 1);
    704 	      *avhere = executable1;
    705 	      memcpy (avhere + 1, argv, new_argc * sizeof(*argv));
    706 	      argv = (char *const *)avhere;
    707 
    708 	      /* Spawn the child. */
    709 #ifndef USE_MINGW_MSYS
    710 	      executable = strrchr (executable1, '\\') + 1;
    711 	      if (!executable)
    712 		executable = executable1;
    713 	      pid = win32_spawn (executable, TRUE, argv, env,
    714 				 dwCreationFlags, si, pi);
    715 #else
    716 	      if (strchr (executable1, '\\') == NULL)
    717 		pid = win32_spawn (executable1, TRUE, argv, env,
    718 				   dwCreationFlags, si, pi);
    719 	      else if (executable1[0] != '\\')
    720 		pid = win32_spawn (executable1, FALSE, argv, env,
    721 				   dwCreationFlags, si, pi);
    722 	      else
    723 		{
    724 		  const char *newex = mingw_rootify (executable1);
    725 		  *avhere = newex;
    726 		  pid = win32_spawn (newex, FALSE, argv, env,
    727 				     dwCreationFlags, si, pi);
    728 		  if (executable1 != newex)
    729 		    free ((char *) newex);
    730 		  if (pid == (pid_t) -1)
    731 		    {
    732 		      newex = msys_rootify (executable1);
    733 		      if (newex != executable1)
    734 			{
    735 			  *avhere = newex;
    736 			  pid = win32_spawn (newex, FALSE, argv, env,
    737 					     dwCreationFlags, si, pi);
    738 			  free ((char *) newex);
    739 			}
    740 		    }
    741 		}
    742 #endif
    743 	      free (avhere);
    744 	    }
    745 	}
    746     }
    747   if (pid == (pid_t) -1)
    748     errno = save_errno;
    749   return pid;
    750 }
    751 
    752 /* Execute a child.  */
    753 
    754 static pid_t
    755 pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags,
    756 		      const char *executable, char * const * argv,
    757                       char* const* env,
    758 		      int in, int out, int errdes,
    759 		      int toclose ATTRIBUTE_UNUSED,
    760 		      const char **errmsg,
    761 		      int *err)
    762 {
    763   pid_t pid;
    764   HANDLE stdin_handle;
    765   HANDLE stdout_handle;
    766   HANDLE stderr_handle;
    767   DWORD dwCreationFlags;
    768   OSVERSIONINFO version_info;
    769   STARTUPINFO si;
    770   PROCESS_INFORMATION pi;
    771   int orig_out, orig_in, orig_err;
    772   BOOL separate_stderr = !(flags & PEX_STDERR_TO_STDOUT);
    773 
    774   /* Ensure we have inheritable descriptors to pass to the child.  */
    775   orig_in = in;
    776   in = _dup (orig_in);
    777 
    778   orig_out = out;
    779   out = _dup (orig_out);
    780 
    781   if (separate_stderr)
    782     {
    783       orig_err = errdes;
    784       errdes = _dup (orig_err);
    785     }
    786 
    787   stdin_handle = INVALID_HANDLE_VALUE;
    788   stdout_handle = INVALID_HANDLE_VALUE;
    789   stderr_handle = INVALID_HANDLE_VALUE;
    790 
    791   stdin_handle = (HANDLE) _get_osfhandle (in);
    792   stdout_handle = (HANDLE) _get_osfhandle (out);
    793   if (separate_stderr)
    794     stderr_handle = (HANDLE) _get_osfhandle (errdes);
    795   else
    796     stderr_handle = stdout_handle;
    797 
    798   /* Determine the version of Windows we are running on.  */
    799   version_info.dwOSVersionInfoSize = sizeof (version_info);
    800   GetVersionEx (&version_info);
    801   if (version_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
    802     /* On Windows 95/98/ME the CREATE_NO_WINDOW flag is not
    803        supported, so we cannot avoid creating a console window.  */
    804     dwCreationFlags = 0;
    805   else
    806     {
    807       HANDLE conout_handle;
    808 
    809       /* Determine whether or not we have an associated console.  */
    810       conout_handle = CreateFile("CONOUT$",
    811 				 GENERIC_WRITE,
    812 				 FILE_SHARE_WRITE,
    813 				 /*lpSecurityAttributes=*/NULL,
    814 				 OPEN_EXISTING,
    815 				 FILE_ATTRIBUTE_NORMAL,
    816 				 /*hTemplateFile=*/NULL);
    817       if (conout_handle == INVALID_HANDLE_VALUE)
    818 	/* There is no console associated with this process.  Since
    819 	   the child is a console process, the OS would normally
    820 	   create a new console Window for the child.  Since we'll be
    821 	   redirecting the child's standard streams, we do not need
    822 	   the console window.  */
    823 	dwCreationFlags = CREATE_NO_WINDOW;
    824       else
    825 	{
    826 	  /* There is a console associated with the process, so the OS
    827 	     will not create a new console.  And, if we use
    828 	     CREATE_NO_WINDOW in this situation, the child will have
    829 	     no associated console.  Therefore, if the child's
    830 	     standard streams are connected to the console, the output
    831 	     will be discarded.  */
    832 	  CloseHandle(conout_handle);
    833 	  dwCreationFlags = 0;
    834 	}
    835     }
    836 
    837   /* Since the child will be a console process, it will, by default,
    838      connect standard input/output to its console.  However, we want
    839      the child to use the handles specifically designated above.  In
    840      addition, if there is no console (such as when we are running in
    841      a Cygwin X window), then we must redirect the child's
    842      input/output, as there is no console for the child to use.  */
    843   memset (&si, 0, sizeof (si));
    844   si.cb = sizeof (si);
    845   si.dwFlags = STARTF_USESTDHANDLES;
    846   si.hStdInput = stdin_handle;
    847   si.hStdOutput = stdout_handle;
    848   si.hStdError = stderr_handle;
    849 
    850   /* Create the child process.  */
    851   pid = win32_spawn (executable, (flags & PEX_SEARCH) != 0,
    852 		     argv, env, dwCreationFlags, &si, &pi);
    853   if (pid == (pid_t) -1)
    854     pid = spawn_script (executable, argv, env, dwCreationFlags,
    855                         &si, &pi);
    856   if (pid == (pid_t) -1)
    857     {
    858       *err = ENOENT;
    859       *errmsg = "CreateProcess";
    860     }
    861 
    862   /* If the child was created successfully, close the original file
    863      descriptors.  If the process creation fails, these are closed by
    864      pex_run_in_environment instead.  We must not close them twice as
    865      that seems to cause a Windows exception.  */
    866 
    867   if (pid != (pid_t) -1)
    868     {
    869       if (orig_in != STDIN_FILENO)
    870 	_close (orig_in);
    871       if (orig_out != STDOUT_FILENO)
    872 	_close (orig_out);
    873       if (separate_stderr
    874 	  && orig_err != STDERR_FILENO)
    875 	_close (orig_err);
    876     }
    877 
    878   /* Close the standard input, standard output and standard error handles
    879      in the parent.  */
    880 
    881   _close (in);
    882   _close (out);
    883   if (separate_stderr)
    884     _close (errdes);
    885 
    886   return pid;
    887 }
    888 
    889 /* Wait for a child process to complete.  MS CRTDLL doesn't return
    890    enough information in status to decide if the child exited due to a
    891    signal or not, rather it simply returns an integer with the exit
    892    code of the child; eg., if the child exited with an abort() call
    893    and didn't have a handler for SIGABRT, it simply returns with
    894    status == 3.  We fix the status code to conform to the usual WIF*
    895    macros.  Note that WIFSIGNALED will never be true under CRTDLL. */
    896 
    897 static pid_t
    898 pex_win32_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid,
    899 		int *status, struct pex_time *time, int done ATTRIBUTE_UNUSED,
    900 		const char **errmsg, int *err)
    901 {
    902   DWORD termstat;
    903   HANDLE h;
    904 
    905   if (time != NULL)
    906     memset (time, 0, sizeof *time);
    907 
    908   h = (HANDLE) pid;
    909 
    910   /* FIXME: If done is non-zero, we should probably try to kill the
    911      process.  */
    912   if (WaitForSingleObject (h, INFINITE) != WAIT_OBJECT_0)
    913     {
    914       CloseHandle (h);
    915       *err = ECHILD;
    916       *errmsg = "WaitForSingleObject";
    917       return -1;
    918     }
    919 
    920   GetExitCodeProcess (h, &termstat);
    921   CloseHandle (h);
    922 
    923   /* A value of 3 indicates that the child caught a signal, but not
    924      which one.  Since only SIGABRT, SIGFPE and SIGINT do anything, we
    925      report SIGABRT.  */
    926   if (termstat == 3)
    927     *status = SIGABRT;
    928   else
    929     *status = (termstat & 0xff) << 8;
    930 
    931   return 0;
    932 }
    933 
    934 /* Create a pipe.  */
    935 
    936 static int
    937 pex_win32_pipe (struct pex_obj *obj ATTRIBUTE_UNUSED, int *p,
    938 		int binary)
    939 {
    940   return _pipe (p, 256, (binary ? _O_BINARY : _O_TEXT) | _O_NOINHERIT);
    941 }
    942 
    943 /* Get a FILE pointer to read from a file descriptor.  */
    944 
    945 static FILE *
    946 pex_win32_fdopenr (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
    947 		   int binary)
    948 {
    949   HANDLE h = (HANDLE) _get_osfhandle (fd);
    950   if (h == INVALID_HANDLE_VALUE)
    951     return NULL;
    952   if (! SetHandleInformation (h, HANDLE_FLAG_INHERIT, 0))
    953     return NULL;
    954   return fdopen (fd, binary ? "rb" : "r");
    955 }
    956 
    957 static FILE *
    958 pex_win32_fdopenw (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
    959 		   int binary)
    960 {
    961   HANDLE h = (HANDLE) _get_osfhandle (fd);
    962   if (h == INVALID_HANDLE_VALUE)
    963     return NULL;
    964   if (! SetHandleInformation (h, HANDLE_FLAG_INHERIT, 0))
    965     return NULL;
    966   return fdopen (fd, binary ? "wb" : "w");
    967 }
    968 
    969 #ifdef MAIN
    970 #include <stdio.h>
    971 
    972 int
    973 main (int argc ATTRIBUTE_UNUSED, char **argv)
    974 {
    975   char const *errmsg;
    976   int err;
    977   argv++;
    978   printf ("%ld\n", (long) pex_win32_exec_child (NULL, PEX_SEARCH, argv[0], argv, NULL, 0, 0, 1, 2, &errmsg, &err));
    979   exit (0);
    980 }
    981 #endif
    982