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
4 Free Software Foundation, Inc.
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.
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.
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. */
22 #include "pex-common.h"
35 #ifdef HAVE_SYS_WAIT_H
46 /* mingw32 headers may not define the following. */
56 # define WAIT_GRANDCHILD 1
59 #define MINGW_NAME "Minimalist GNU for Windows"
60 #define MINGW_NAME_LEN (sizeof(MINGW_NAME) - 1)
62 /* Ensure that the executable pathname uses Win32 backslashes. This
63 is not necessary on NT, but on W9x, forward slashes causes
64 failure of spawn* and exec* functions (and probably any function
65 that calls CreateProcess) *iff* the executable pathname (argv[0])
66 is a quoted string. And quoting is necessary in case a pathname
67 contains embedded white space. You can't win. */
69 backslashify (char *s
)
71 while ((s
= strchr (s
, '/')) != NULL
)
76 static int pex_win32_open_read (struct pex_obj
*, const char *, int);
77 static int pex_win32_open_write (struct pex_obj
*, const char *, int);
78 static long pex_win32_exec_child (struct pex_obj
*, int, const char *,
79 char * const *, int, int, int,
80 const char **, int *);
81 static int pex_win32_close (struct pex_obj
*, int);
82 static int pex_win32_wait (struct pex_obj
*, long, int *,
83 struct pex_time
*, int, const char **, int *);
84 static int pex_win32_pipe (struct pex_obj
*, int *, int);
85 static FILE *pex_win32_fdopenr (struct pex_obj
*, int, int);
86 static FILE *pex_win32_fdopenw (struct pex_obj
*, int, int);
88 /* The list of functions we pass to the common routines. */
90 const struct pex_funcs funcs
=
103 /* Return a newly initialized pex_obj structure. */
106 pex_init (int flags
, const char *pname
, const char *tempbase
)
108 return pex_init_common (flags
, pname
, tempbase
, &funcs
);
111 /* Open a file for reading. */
114 pex_win32_open_read (struct pex_obj
*obj ATTRIBUTE_UNUSED
, const char *name
,
117 return _open (name
, _O_RDONLY
| (binary
? _O_BINARY
: _O_TEXT
));
120 /* Open a file for writing. */
123 pex_win32_open_write (struct pex_obj
*obj ATTRIBUTE_UNUSED
, const char *name
,
126 /* Note that we can't use O_EXCL here because gcc may have already
127 created the temporary file via make_temp_file. */
129 (_O_WRONLY
| _O_CREAT
| _O_TRUNC
130 | (binary
? _O_BINARY
: _O_TEXT
)),
131 _S_IREAD
| _S_IWRITE
);
137 pex_win32_close (struct pex_obj
*obj ATTRIBUTE_UNUSED
, int fd
)
142 #ifdef USE_MINGW_MSYS
143 static const char *mingw_keys
[] = {"SOFTWARE", "Microsoft", "Windows", "CurrentVersion", "Uninstall", NULL
};
145 /* Tack the executable on the end of a (possibly slash terminated) buffer
146 and convert everything to \. */
148 tack_on_executable (char *buf
, const char *executable
)
150 char *p
= strchr (buf
, '\0');
151 if (p
> buf
&& (p
[-1] == '\\' || p
[-1] == '/'))
153 backslashify (strcat (buf
, executable
));
157 /* Walk down a registry hierarchy until the end. Return the key. */
159 openkey (HKEY hStart
, const char *keys
[])
162 for (hKey
= hStart
; *keys
; keys
++)
166 res
= RegOpenKey (hTmp
, *keys
, &hKey
);
168 if (hTmp
!= HKEY_LOCAL_MACHINE
)
171 if (res
!= ERROR_SUCCESS
)
177 /* Return the "mingw root" as derived from the mingw uninstall information. */
179 mingw_rootify (const char *executable
)
183 char *namebuf
, *foundbuf
;
187 /* Open the uninstall "directory". */
188 hKey
= openkey (HKEY_LOCAL_MACHINE
, mingw_keys
);
194 /* Need to enumerate all of the keys here looking for one the most recent
196 if (RegQueryInfoKey (hKey
, NULL
, NULL
, NULL
, NULL
, &maxlen
, NULL
, NULL
,
197 NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
202 namebuf
= XNEWVEC (char, ++maxlen
);
203 foundbuf
= XNEWVEC (char, maxlen
);
205 if (!namebuf
|| !foundbuf
)
215 /* Look through all of the keys for one that begins with Minimal GNU...
216 Try to get the latest version by doing a string compare although that
217 string never really works with version number sorting. */
218 for (i
= 0; RegEnumKey (hKey
, i
, namebuf
, maxlen
) == ERROR_SUCCESS
; i
++)
220 int match
= strcasecmp (namebuf
, MINGW_NAME
);
223 if (match
> 0 && strncasecmp (namebuf
, MINGW_NAME
, MINGW_NAME_LEN
) > 0)
225 if (strcasecmp (namebuf
, foundbuf
) > 0)
226 strcpy (foundbuf
, namebuf
);
230 /* If foundbuf is empty, we didn't find anything. Punt. */
238 /* Open the key that we wanted */
239 res
= RegOpenKey (hKey
, foundbuf
, &hTmp
);
243 /* Don't know why this would fail, but you gotta check */
244 if (res
!= ERROR_SUCCESS
)
248 /* Get the length of the value pointed to by InstallLocation */
249 if (RegQueryValueEx (hTmp
, "InstallLocation", 0, NULL
, NULL
,
250 &maxlen
) != ERROR_SUCCESS
|| maxlen
== 0)
256 /* Allocate space for the install location */
257 foundbuf
= XNEWVEC (char, maxlen
+ strlen (executable
));
264 /* Read the install location into the buffer */
265 res
= RegQueryValueEx (hTmp
, "InstallLocation", 0, NULL
, (LPBYTE
) foundbuf
,
268 if (res
!= ERROR_SUCCESS
)
274 /* Concatenate the install location and the executable, turn all slashes
275 to backslashes, and return that. */
276 return tack_on_executable (foundbuf
, executable
);
279 /* Read the install location of msys from it's installation file and
280 rootify the executable based on that. */
282 msys_rootify (const char *executable
)
285 size_t execlen
= strlen (executable
) + 1;
290 buf
= XNEWVEC (char, bufsize
+ execlen
);
293 res
= GetPrivateProfileString ("InstallSettings", "InstallPath", NULL
,
294 buf
, bufsize
, "msys.ini");
297 if (strlen (buf
) < bufsize
)
310 return tack_on_executable (buf
, executable
);
319 /* Return a Windows command-line from ARGV. It is the caller's
320 responsibility to free the string returned. */
323 argv_to_cmdline (char *const *argv
)
331 for (i
= 0; argv
[i
]; i
++)
333 /* We quote every last argument. This simplifies the problem;
334 we need only escape embedded double-quotes and immediately
335 preceeding backslash characters. A sequence of backslach characters
336 that is not follwed by a double quote character will not be
338 for (j
= 0; argv
[i
][j
]; j
++)
340 if (argv
[i
][j
] == '"')
342 /* Escape preceeding backslashes. */
343 for (k
= j
- 1; k
>= 0 && argv
[i
][k
] == '\\'; k
--)
345 /* Escape the qote character. */
349 /* Trailing backslashes also need to be escaped because they will be
350 followed by the terminating quote. */
351 for (k
= j
- 1; k
>= 0 && argv
[i
][k
] == '\\'; k
--)
354 cmdline_len
+= 3; /* for leading and trailing quotes and space */
356 cmdline
= xmalloc (cmdline_len
);
358 for (i
= 0; argv
[i
]; i
++)
361 for (j
= 0; argv
[i
][j
]; j
++)
363 if (argv
[i
][j
] == '"')
365 for (k
= j
- 1; k
>= 0 && argv
[i
][k
] == '\\'; k
--)
371 for (k
= j
- 1; k
>= 0 && argv
[i
][k
] == '\\'; k
--)
380 static const char *const
388 static const char *const
394 /* Returns the full path to PROGRAM. If SEARCH is true, look for
395 PROGRAM in each directory in PATH. */
398 find_executable (const char *program
, BOOL search
)
400 char *full_executable
;
403 const char *path
= 0;
404 const char *const *ext
;
406 size_t proglen
= strlen (program
);
407 int has_extension
= !!strchr (program
, '.');
408 int has_slash
= (strchr (program
, '/') || strchr (program
, '\\'));
415 path
= getenv ("PATH");
420 for (p
= path
; *p
; p
= q
)
423 while (*q
!= ';' && *q
!= '\0')
425 if ((size_t)(q
- p
) > fe_len
)
430 fe_len
= fe_len
+ 1 + proglen
+ (has_extension
? 1 : 5);
431 full_executable
= xmalloc (fe_len
);
437 while (*q
!= ';' && *q
!= '\0')
441 memcpy (e
, p
, q
- p
);
450 for (e
= full_executable
; *e
; e
++)
454 /* At this point, e points to the terminating NUL character for
456 for (ext
= has_extension
? no_suffixes
: std_suffixes
; *ext
; ext
++)
458 /* Remove any current extension. */
460 /* Add the new one. */
461 strcat (full_executable
, *ext
);
463 /* Attempt to open this file. */
464 h
= CreateFile (full_executable
, GENERIC_READ
,
465 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
466 0, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0);
467 if (h
!= INVALID_HANDLE_VALUE
)
473 free (full_executable
);
478 return full_executable
;
481 /* Low-level process creation function. */
484 win32_spawn (const char *executable
,
487 DWORD dwCreationFlags
,
489 LPPROCESS_INFORMATION pi
)
491 char *full_executable
;
494 full_executable
= NULL
;
497 full_executable
= find_executable (executable
, search
);
498 if (!full_executable
)
500 cmdline
= argv_to_cmdline (argv
);
504 /* Create the child process. */
505 if (!CreateProcess (full_executable
, cmdline
,
506 /*lpProcessAttributes=*/NULL
,
507 /*lpThreadAttributes=*/NULL
,
508 /*bInheritHandles=*/TRUE
,
510 /*lpEnvironment=*/NULL
,
511 /*lpCurrentDirectory=*/NULL
,
515 free (full_executable
);
520 CloseHandle (pi
->hThread
);
521 free (full_executable
);
523 return (long) pi
->hProcess
;
529 free (full_executable
);
534 spawn_script (const char *executable
, char *const *argv
,
535 DWORD dwCreationFlags
,
537 LPPROCESS_INFORMATION pi
)
540 int save_errno
= errno
;
541 int fd
= _open (executable
, _O_RDONLY
);
545 char buf
[MAX_PATH
+ 5];
546 int len
= _read (fd
, buf
, sizeof (buf
) - 1);
552 eol
= strchr (buf
, '\n');
553 if (eol
&& strncmp (buf
, "#!", 2) == 0)
556 const char ** avhere
= (const char **) --argv
;
559 while (*--eol
== '\r' || *eol
== ' ' || *eol
== '\t');
560 for (executable1
= buf
+ 2; *executable1
== ' ' || *executable1
== '\t'; executable1
++)
563 backslashify (executable1
);
564 *avhere
= executable1
;
565 #ifndef USE_MINGW_MSYS
566 executable
= strrchr (executable1
, '\\') + 1;
568 executable
= executable1
;
569 pid
= win32_spawn (executable
, TRUE
, argv
,
570 dwCreationFlags
, si
, pi
);
572 if (strchr (executable1
, '\\') == NULL
)
573 pid
= win32_spawn (executable1
, TRUE
, argv
,
574 dwCreationFlags
, si
, pi
);
575 else if (executable1
[0] != '\\')
576 pid
= win32_spawn (executable1
, FALSE
, argv
,
577 dwCreationFlags
, si
, pi
);
580 const char *newex
= mingw_rootify (executable1
);
582 pid
= win32_spawn (newex
, FALSE
, argv
,
583 dwCreationFlags
, si
, pi
);
584 if (executable1
!= newex
)
585 free ((char *) newex
);
588 newex
= msys_rootify (executable1
);
589 if (newex
!= executable1
)
592 pid
= win32_spawn (newex
, FALSE
, argv
,
593 dwCreationFlags
, si
, pi
);
594 free ((char *) newex
);
607 /* Execute a child. */
610 pex_win32_exec_child (struct pex_obj
*obj ATTRIBUTE_UNUSED
, int flags
,
611 const char *executable
, char * const * argv
,
612 int in
, int out
, int errdes
, const char **errmsg
,
617 HANDLE stdout_handle
;
618 HANDLE stderr_handle
;
619 DWORD dwCreationFlags
;
620 OSVERSIONINFO version_info
;
622 PROCESS_INFORMATION pi
;
624 stdin_handle
= INVALID_HANDLE_VALUE
;
625 stdout_handle
= INVALID_HANDLE_VALUE
;
626 stderr_handle
= INVALID_HANDLE_VALUE
;
628 stdin_handle
= (HANDLE
) _get_osfhandle (in
);
629 stdout_handle
= (HANDLE
) _get_osfhandle (out
);
630 if (!(flags
& PEX_STDERR_TO_STDOUT
))
631 stderr_handle
= (HANDLE
) _get_osfhandle (errdes
);
633 stderr_handle
= stdout_handle
;
635 /* Determine the version of Windows we are running on. */
636 version_info
.dwOSVersionInfoSize
= sizeof (version_info
);
637 GetVersionEx (&version_info
);
638 if (version_info
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
)
639 /* On Windows 95/98/ME the CREATE_NO_WINDOW flag is not
640 supported, so we cannot avoid creating a console window. */
644 HANDLE conout_handle
;
646 /* Determine whether or not we have an associated console. */
647 conout_handle
= CreateFile("CONOUT$",
650 /*lpSecurityAttributes=*/NULL
,
652 FILE_ATTRIBUTE_NORMAL
,
653 /*hTemplateFile=*/NULL
);
654 if (conout_handle
== INVALID_HANDLE_VALUE
)
655 /* There is no console associated with this process. Since
656 the child is a console process, the OS would normally
657 create a new console Window for the child. Since we'll be
658 redirecting the child's standard streams, we do not need
659 the console window. */
660 dwCreationFlags
= CREATE_NO_WINDOW
;
663 /* There is a console associated with the process, so the OS
664 will not create a new console. And, if we use
665 CREATE_NO_WINDOW in this situation, the child will have
666 no associated console. Therefore, if the child's
667 standard streams are connected to the console, the output
668 will be discarded. */
669 CloseHandle(conout_handle
);
674 /* Since the child will be a console process, it will, by default,
675 connect standard input/output to its console. However, we want
676 the child to use the handles specifically designated above. In
677 addition, if there is no console (such as when we are running in
678 a Cygwin X window), then we must redirect the child's
679 input/output, as there is no console for the child to use. */
680 memset (&si
, 0, sizeof (si
));
682 si
.dwFlags
= STARTF_USESTDHANDLES
;
683 si
.hStdInput
= stdin_handle
;
684 si
.hStdOutput
= stdout_handle
;
685 si
.hStdError
= stderr_handle
;
687 /* Create the child process. */
688 pid
= win32_spawn (executable
, (flags
& PEX_SEARCH
) != 0,
689 argv
, dwCreationFlags
, &si
, &pi
);
691 pid
= spawn_script (executable
, argv
, dwCreationFlags
, &si
, &pi
);
695 *errmsg
= "CreateProcess";
698 /* Close the standard output and standard error handles in the
700 if (out
!= STDOUT_FILENO
)
701 obj
->funcs
->close (obj
, out
);
702 if (errdes
!= STDERR_FILENO
)
703 obj
->funcs
->close (obj
, errdes
);
708 /* Wait for a child process to complete. MS CRTDLL doesn't return
709 enough information in status to decide if the child exited due to a
710 signal or not, rather it simply returns an integer with the exit
711 code of the child; eg., if the child exited with an abort() call
712 and didn't have a handler for SIGABRT, it simply returns with
713 status == 3. We fix the status code to conform to the usual WIF*
714 macros. Note that WIFSIGNALED will never be true under CRTDLL. */
717 pex_win32_wait (struct pex_obj
*obj ATTRIBUTE_UNUSED
, long pid
,
718 int *status
, struct pex_time
*time
, int done ATTRIBUTE_UNUSED
,
719 const char **errmsg
, int *err
)
725 memset (time
, 0, sizeof *time
);
729 /* FIXME: If done is non-zero, we should probably try to kill the
731 if (WaitForSingleObject (h
, INFINITE
) != WAIT_OBJECT_0
)
735 *errmsg
= "WaitForSingleObject";
739 GetExitCodeProcess (h
, &termstat
);
742 /* A value of 3 indicates that the child caught a signal, but not
743 which one. Since only SIGABRT, SIGFPE and SIGINT do anything, we
748 *status
= (termstat
& 0xff) << 8;
756 pex_win32_pipe (struct pex_obj
*obj ATTRIBUTE_UNUSED
, int *p
,
759 return _pipe (p
, 256, binary
? _O_BINARY
: _O_TEXT
);
762 /* Get a FILE pointer to read from a file descriptor. */
765 pex_win32_fdopenr (struct pex_obj
*obj ATTRIBUTE_UNUSED
, int fd
,
768 return fdopen (fd
, binary
? "rb" : "r");
772 pex_win32_fdopenw (struct pex_obj
*obj ATTRIBUTE_UNUSED
, int fd
,
775 HANDLE h
= (HANDLE
) _get_osfhandle (fd
);
776 if (h
== INVALID_HANDLE_VALUE
)
778 if (! SetHandleInformation (h
, HANDLE_FLAG_INHERIT
, 0))
780 return fdopen (fd
, binary
? "wb" : "w");
787 main (int argc ATTRIBUTE_UNUSED
, char **argv
)
792 printf ("%ld\n", pex_win32_exec_child (NULL
, PEX_SEARCH
, argv
[0], argv
, 0, 1, 2, &errmsg
, &err
));