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