Automatic date update in version.in
[platform/upstream/binutils.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, 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