Sync libiberty sources with gcc mainline.
[external/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       if (j == 0)
374         needs_quotes = 1;
375       /* Trailing backslashes also need to be escaped because they will be
376          followed by the terminating quote.  */
377       if (needs_quotes)
378         {
379           for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
380             cmdline_len++;
381         }
382       cmdline_len += j;
383       /* for leading and trailing quotes and space */
384       cmdline_len += needs_quotes * 2 + 1;
385     }
386   cmdline = XNEWVEC (char, cmdline_len);
387   p = cmdline;
388   for (i = 0; argv[i]; i++)
389     {
390       needs_quotes = 0;
391       for (j = 0; argv[i][j]; j++)
392         {
393           if (argv[i][j] == ' ' || argv[i][j] == '\t' || argv[i][j] == '"')
394             {
395               needs_quotes = 1;
396               break;
397             }
398         }
399       if (j == 0)
400         needs_quotes = 1;
401
402       if (needs_quotes)
403         {
404           *p++ = '"';
405         }
406       for (j = 0; argv[i][j]; j++)
407         {
408           if (argv[i][j] == '"')
409             {
410               for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
411                 *p++ = '\\';
412               *p++ = '\\';
413             }
414           *p++ = argv[i][j];
415         }
416       if (needs_quotes)
417         {
418           for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
419             *p++ = '\\';
420           *p++ = '"';
421         }
422       *p++ = ' ';
423     }
424   p[-1] = '\0';
425   return cmdline;
426 }
427
428 /* We'll try the passed filename with all the known standard
429    extensions, and then without extension.  We try no extension
430    last so that we don't try to run some random extension-less
431    file that might be hanging around.  We try both extension
432    and no extension so that we don't need any fancy logic
433    to determine if a file has extension.  */
434 static const char *const
435 std_suffixes[] = {
436   ".com",
437   ".exe",
438   ".bat",
439   ".cmd",
440   "",
441   0
442 };
443
444 /* Returns the full path to PROGRAM.  If SEARCH is true, look for
445    PROGRAM in each directory in PATH.  */
446
447 static char *
448 find_executable (const char *program, BOOL search)
449 {
450   char *full_executable;
451   char *e;
452   size_t fe_len;
453   const char *path = 0;
454   const char *const *ext;
455   const char *p, *q;
456   size_t proglen = strlen (program);
457   int has_slash = (strchr (program, '/') || strchr (program, '\\'));
458   HANDLE h;
459
460   if (has_slash)
461     search = FALSE;
462
463   if (search)
464     path = getenv ("PATH");
465   if (!path)
466     path = "";
467
468   fe_len = 0;
469   for (p = path; *p; p = q)
470     {
471       q = p;
472       while (*q != ';' && *q != '\0')
473         q++;
474       if ((size_t)(q - p) > fe_len)
475         fe_len = q - p;
476       if (*q == ';')
477         q++;
478     }
479   fe_len = fe_len + 1 + proglen + 5 /* space for extension */;
480   full_executable = XNEWVEC (char, fe_len);
481
482   p = path;
483   do
484     {
485       q = p;
486       while (*q != ';' && *q != '\0')
487         q++;
488
489       e = full_executable;
490       memcpy (e, p, q - p);
491       e += (q - p);
492       if (q - p)
493         *e++ = '\\';
494       strcpy (e, program);
495
496       if (*q == ';')
497         q++;
498
499       for (e = full_executable; *e; e++)
500         if (*e == '/')
501           *e = '\\';
502
503       /* At this point, e points to the terminating NUL character for
504          full_executable.  */
505       for (ext = std_suffixes; *ext; ext++)
506         {
507           /* Remove any current extension.  */
508           *e = '\0';
509           /* Add the new one.  */
510           strcat (full_executable, *ext);
511
512           /* Attempt to open this file.  */
513           h = CreateFile (full_executable, GENERIC_READ,
514                           FILE_SHARE_READ | FILE_SHARE_WRITE,
515                           0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
516           if (h != INVALID_HANDLE_VALUE)
517             goto found;
518         }
519       p = q;
520     }
521   while (*p);
522   free (full_executable);
523   return 0;
524
525  found:
526   CloseHandle (h);
527   return full_executable;
528 }
529
530 /* Low-level process creation function and helper.  */
531
532 static int
533 env_compare (const void *a_ptr, const void *b_ptr)
534 {
535   const char *a;
536   const char *b;
537   unsigned char c1;
538   unsigned char c2;
539
540   a = *(const char **) a_ptr;
541   b = *(const char **) b_ptr;
542
543   /* a and b will be of the form: VAR=VALUE
544      We compare only the variable name part here using a case-insensitive
545      comparison algorithm.  It might appear that in fact strcasecmp () can
546      take the place of this whole function, and indeed it could, save for
547      the fact that it would fail in cases such as comparing A1=foo and
548      A=bar (because 1 is less than = in the ASCII character set).
549      (Environment variables containing no numbers would work in such a
550      scenario.)  */
551
552   do
553     {
554       c1 = (unsigned char) tolower (*a++);
555       c2 = (unsigned char) tolower (*b++);
556
557       if (c1 == '=')
558         c1 = '\0';
559
560       if (c2 == '=')
561         c2 = '\0';
562     }
563   while (c1 == c2 && c1 != '\0');
564
565   return c1 - c2;
566 }
567
568 /* Execute a Windows executable as a child process.  This will fail if the
569  * target is not actually an executable, such as if it is a shell script. */
570
571 static pid_t
572 win32_spawn (const char *executable,
573              BOOL search,
574              char *const *argv,
575              char *const *env, /* array of strings of the form: VAR=VALUE */
576              DWORD dwCreationFlags,
577              LPSTARTUPINFO si,
578              LPPROCESS_INFORMATION pi)
579 {
580   char *full_executable;
581   char *cmdline;
582   char **env_copy;
583   char *env_block = NULL;
584
585   full_executable = NULL;
586   cmdline = NULL;
587
588   if (env)
589     {
590       int env_size;
591
592       /* Count the number of environment bindings supplied.  */
593       for (env_size = 0; env[env_size]; env_size++)
594         continue;
595     
596       /* Assemble an environment block, if required.  This consists of
597          VAR=VALUE strings juxtaposed (with one null character between each
598          pair) and an additional null at the end.  */
599       if (env_size > 0)
600         {
601           int var;
602           int total_size = 1; /* 1 is for the final null.  */
603           char *bufptr;
604     
605           /* Windows needs the members of the block to be sorted by variable
606              name.  */
607           env_copy = (char **) alloca (sizeof (char *) * env_size);
608           memcpy (env_copy, env, sizeof (char *) * env_size);
609           qsort (env_copy, env_size, sizeof (char *), env_compare);
610     
611           for (var = 0; var < env_size; var++)
612             total_size += strlen (env[var]) + 1;
613     
614           env_block = XNEWVEC (char, total_size);
615           bufptr = env_block;
616           for (var = 0; var < env_size; var++)
617             bufptr = stpcpy (bufptr, env_copy[var]) + 1;
618     
619           *bufptr = '\0';
620         }
621     }
622
623   full_executable = find_executable (executable, search);
624   if (!full_executable)
625     goto error;
626   cmdline = argv_to_cmdline (argv);
627   if (!cmdline)
628     goto error;
629     
630   /* Create the child process.  */  
631   if (!CreateProcess (full_executable, cmdline, 
632                       /*lpProcessAttributes=*/NULL,
633                       /*lpThreadAttributes=*/NULL,
634                       /*bInheritHandles=*/TRUE,
635                       dwCreationFlags,
636                       (LPVOID) env_block,
637                       /*lpCurrentDirectory=*/NULL,
638                       si,
639                       pi))
640     {
641       free (env_block);
642
643       free (full_executable);
644
645       return (pid_t) -1;
646     }
647
648   /* Clean up.  */
649   CloseHandle (pi->hThread);
650   free (full_executable);
651   free (env_block);
652
653   return (pid_t) pi->hProcess;
654
655  error:
656   free (env_block);
657   free (cmdline);
658   free (full_executable);
659
660   return (pid_t) -1;
661 }
662
663 /* Spawn a script.  This simulates the Unix script execution mechanism.
664    This function is called as a fallback if win32_spawn fails. */
665
666 static pid_t
667 spawn_script (const char *executable, char *const *argv,
668               char* const *env,
669               DWORD dwCreationFlags,
670               LPSTARTUPINFO si,
671               LPPROCESS_INFORMATION pi)
672 {
673   pid_t pid = (pid_t) -1;
674   int save_errno = errno;
675   int fd = _open (executable, _O_RDONLY);
676
677   /* Try to open script, check header format, extract interpreter path,
678      and spawn script using that interpretter. */
679   if (fd >= 0)
680     {
681       char buf[MAX_PATH + 5];
682       int len = _read (fd, buf, sizeof (buf) - 1);
683       _close (fd);
684       if (len > 3)
685         {
686           char *eol;
687           buf[len] = '\0';
688           eol = strchr (buf, '\n');
689           if (eol && strncmp (buf, "#!", 2) == 0)
690             {
691             
692               /* Header format is OK. */
693               char *executable1;
694               int new_argc;
695               const char **avhere;
696
697               /* Extract interpreter path. */
698               do
699                 *eol = '\0';
700               while (*--eol == '\r' || *eol == ' ' || *eol == '\t');
701               for (executable1 = buf + 2; *executable1 == ' ' || *executable1 == '\t'; executable1++)
702                 continue;
703               backslashify (executable1);
704
705               /* Duplicate argv, prepending the interpreter path. */
706               new_argc = argv_to_argc (argv) + 1;
707               avhere = XNEWVEC (const char *, new_argc + 1);
708               *avhere = executable1;
709               memcpy (avhere + 1, argv, new_argc * sizeof(*argv));
710               argv = (char *const *)avhere;
711
712               /* Spawn the child. */
713 #ifndef USE_MINGW_MSYS
714               executable = strrchr (executable1, '\\') + 1;
715               if (!executable)
716                 executable = executable1;
717               pid = win32_spawn (executable, TRUE, argv, env,
718                                  dwCreationFlags, si, pi);
719 #else
720               if (strchr (executable1, '\\') == NULL)
721                 pid = win32_spawn (executable1, TRUE, argv, env,
722                                    dwCreationFlags, si, pi);
723               else if (executable1[0] != '\\')
724                 pid = win32_spawn (executable1, FALSE, argv, env,
725                                    dwCreationFlags, si, pi);
726               else
727                 {
728                   const char *newex = mingw_rootify (executable1);
729                   *avhere = newex;
730                   pid = win32_spawn (newex, FALSE, argv, env,
731                                      dwCreationFlags, si, pi);
732                   if (executable1 != newex)
733                     free ((char *) newex);
734                   if (pid == (pid_t) -1)
735                     {
736                       newex = msys_rootify (executable1);
737                       if (newex != executable1)
738                         {
739                           *avhere = newex;
740                           pid = win32_spawn (newex, FALSE, argv, env,
741                                              dwCreationFlags, si, pi);
742                           free ((char *) newex);
743                         }
744                     }
745                 }
746 #endif
747               free (avhere);
748             }
749         }
750     }
751   if (pid == (pid_t) -1)
752     errno = save_errno;
753   return pid;
754 }
755
756 /* Execute a child.  */
757
758 static pid_t
759 pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags,
760                       const char *executable, char * const * argv,
761                       char* const* env,
762                       int in, int out, int errdes,
763                       int toclose ATTRIBUTE_UNUSED,
764                       const char **errmsg,
765                       int *err)
766 {
767   pid_t pid;
768   HANDLE stdin_handle;
769   HANDLE stdout_handle;
770   HANDLE stderr_handle;
771   DWORD dwCreationFlags;
772   OSVERSIONINFO version_info;
773   STARTUPINFO si;
774   PROCESS_INFORMATION pi;
775   int orig_out, orig_in, orig_err;
776   BOOL separate_stderr = !(flags & PEX_STDERR_TO_STDOUT);
777
778   /* Ensure we have inheritable descriptors to pass to the child.  */
779   orig_in = in;
780   in = _dup (orig_in);
781   
782   orig_out = out;
783   out = _dup (orig_out);
784   
785   if (separate_stderr)
786     {
787       orig_err = errdes;
788       errdes = _dup (orig_err);
789     }
790
791   stdin_handle = INVALID_HANDLE_VALUE;
792   stdout_handle = INVALID_HANDLE_VALUE;
793   stderr_handle = INVALID_HANDLE_VALUE;
794
795   stdin_handle = (HANDLE) _get_osfhandle (in);
796   stdout_handle = (HANDLE) _get_osfhandle (out);
797   if (separate_stderr)
798     stderr_handle = (HANDLE) _get_osfhandle (errdes);
799   else
800     stderr_handle = stdout_handle;
801
802   /* Determine the version of Windows we are running on.  */
803   version_info.dwOSVersionInfoSize = sizeof (version_info); 
804   GetVersionEx (&version_info);
805   if (version_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
806     /* On Windows 95/98/ME the CREATE_NO_WINDOW flag is not
807        supported, so we cannot avoid creating a console window.  */
808     dwCreationFlags = 0;
809   else
810     {
811       HANDLE conout_handle;
812
813       /* Determine whether or not we have an associated console.  */
814       conout_handle = CreateFile("CONOUT$", 
815                                  GENERIC_WRITE,
816                                  FILE_SHARE_WRITE,
817                                  /*lpSecurityAttributes=*/NULL,
818                                  OPEN_EXISTING,
819                                  FILE_ATTRIBUTE_NORMAL,
820                                  /*hTemplateFile=*/NULL);
821       if (conout_handle == INVALID_HANDLE_VALUE)
822         /* There is no console associated with this process.  Since
823            the child is a console process, the OS would normally
824            create a new console Window for the child.  Since we'll be
825            redirecting the child's standard streams, we do not need
826            the console window.  */ 
827         dwCreationFlags = CREATE_NO_WINDOW;
828       else 
829         {
830           /* There is a console associated with the process, so the OS
831              will not create a new console.  And, if we use
832              CREATE_NO_WINDOW in this situation, the child will have
833              no associated console.  Therefore, if the child's
834              standard streams are connected to the console, the output
835              will be discarded.  */
836           CloseHandle(conout_handle);
837           dwCreationFlags = 0;
838         }
839     }
840
841   /* Since the child will be a console process, it will, by default,
842      connect standard input/output to its console.  However, we want
843      the child to use the handles specifically designated above.  In
844      addition, if there is no console (such as when we are running in
845      a Cygwin X window), then we must redirect the child's
846      input/output, as there is no console for the child to use.  */
847   memset (&si, 0, sizeof (si));
848   si.cb = sizeof (si);
849   si.dwFlags = STARTF_USESTDHANDLES;
850   si.hStdInput = stdin_handle;
851   si.hStdOutput = stdout_handle;
852   si.hStdError = stderr_handle;
853
854   /* Create the child process.  */  
855   pid = win32_spawn (executable, (flags & PEX_SEARCH) != 0,
856                      argv, env, dwCreationFlags, &si, &pi);
857   if (pid == (pid_t) -1)
858     pid = spawn_script (executable, argv, env, dwCreationFlags,
859                         &si, &pi);
860   if (pid == (pid_t) -1)
861     {
862       *err = ENOENT;
863       *errmsg = "CreateProcess";
864     }
865
866   /* If the child was created successfully, close the original file
867      descriptors.  If the process creation fails, these are closed by
868      pex_run_in_environment instead.  We must not close them twice as
869      that seems to cause a Windows exception.  */
870      
871   if (pid != (pid_t) -1)
872     {
873       if (orig_in != STDIN_FILENO)
874         _close (orig_in);
875       if (orig_out != STDOUT_FILENO)
876         _close (orig_out);
877       if (separate_stderr
878           && orig_err != STDERR_FILENO)
879         _close (orig_err);
880     }
881
882   /* Close the standard input, standard output and standard error handles
883      in the parent.  */ 
884
885   _close (in);
886   _close (out);
887   if (separate_stderr)
888     _close (errdes);
889
890   return pid;
891 }
892
893 /* Wait for a child process to complete.  MS CRTDLL doesn't return
894    enough information in status to decide if the child exited due to a
895    signal or not, rather it simply returns an integer with the exit
896    code of the child; eg., if the child exited with an abort() call
897    and didn't have a handler for SIGABRT, it simply returns with
898    status == 3.  We fix the status code to conform to the usual WIF*
899    macros.  Note that WIFSIGNALED will never be true under CRTDLL. */
900
901 static pid_t
902 pex_win32_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid,
903                 int *status, struct pex_time *time, int done ATTRIBUTE_UNUSED,
904                 const char **errmsg, int *err)
905 {
906   DWORD termstat;
907   HANDLE h;
908
909   if (time != NULL)
910     memset (time, 0, sizeof *time);
911
912   h = (HANDLE) pid;
913
914   /* FIXME: If done is non-zero, we should probably try to kill the
915      process.  */
916   if (WaitForSingleObject (h, INFINITE) != WAIT_OBJECT_0)
917     {
918       CloseHandle (h);
919       *err = ECHILD;
920       *errmsg = "WaitForSingleObject";
921       return -1;
922     }
923
924   GetExitCodeProcess (h, &termstat);
925   CloseHandle (h);
926  
927   /* A value of 3 indicates that the child caught a signal, but not
928      which one.  Since only SIGABRT, SIGFPE and SIGINT do anything, we
929      report SIGABRT.  */
930   if (termstat == 3)
931     *status = SIGABRT;
932   else
933     *status = (termstat & 0xff) << 8;
934
935   return 0;
936 }
937
938 /* Create a pipe.  */
939
940 static int
941 pex_win32_pipe (struct pex_obj *obj ATTRIBUTE_UNUSED, int *p,
942                 int binary)
943 {
944   return _pipe (p, 256, (binary ? _O_BINARY : _O_TEXT) | _O_NOINHERIT);
945 }
946
947 /* Get a FILE pointer to read from a file descriptor.  */
948
949 static FILE *
950 pex_win32_fdopenr (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
951                    int binary)
952 {
953   HANDLE h = (HANDLE) _get_osfhandle (fd);
954   if (h == INVALID_HANDLE_VALUE)
955     return NULL;
956   if (! SetHandleInformation (h, HANDLE_FLAG_INHERIT, 0))
957     return NULL;
958   return fdopen (fd, binary ? "rb" : "r");
959 }
960
961 static FILE *
962 pex_win32_fdopenw (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
963                    int binary)
964 {
965   HANDLE h = (HANDLE) _get_osfhandle (fd);
966   if (h == INVALID_HANDLE_VALUE)
967     return NULL;
968   if (! SetHandleInformation (h, HANDLE_FLAG_INHERIT, 0))
969     return NULL;
970   return fdopen (fd, binary ? "wb" : "w");
971 }
972
973 #ifdef MAIN
974 #include <stdio.h>
975
976 int
977 main (int argc ATTRIBUTE_UNUSED, char **argv)
978 {
979   char const *errmsg;
980   int err;
981   argv++;
982   printf ("%ld\n", (long) pex_win32_exec_child (NULL, PEX_SEARCH, argv[0], argv, NULL, 0, 0, 1, 2, &errmsg, &err));
983   exit (0);
984 }
985 #endif