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