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);
87 /* The list of functions we pass to the common routines. */
89 const struct pex_funcs funcs =
101 /* Return a newly initialized pex_obj structure. */
104 pex_init (int flags, const char *pname, const char *tempbase)
106 return pex_init_common (flags, pname, tempbase, &funcs);
109 /* Open a file for reading. */
112 pex_win32_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
115 return _open (name, _O_RDONLY | (binary ? _O_BINARY : _O_TEXT));
118 /* Open a file for writing. */
121 pex_win32_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
124 /* Note that we can't use O_EXCL here because gcc may have already
125 created the temporary file via make_temp_file. */
127 (_O_WRONLY | _O_CREAT | _O_TRUNC
128 | (binary ? _O_BINARY : _O_TEXT)),
129 _S_IREAD | _S_IWRITE);
135 pex_win32_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd)
140 #ifdef USE_MINGW_MSYS
141 static const char *mingw_keys[] = {"SOFTWARE", "Microsoft", "Windows", "CurrentVersion", "Uninstall", NULL};
143 /* Tack the executable on the end of a (possibly slash terminated) buffer
144 and convert everything to \. */
146 tack_on_executable (char *buf, const char *executable)
148 char *p = strchr (buf, '\0');
149 if (p > buf && (p[-1] == '\\' || p[-1] == '/'))
151 backslashify (strcat (buf, executable));
155 /* Walk down a registry hierarchy until the end. Return the key. */
157 openkey (HKEY hStart, const char *keys[])
160 for (hKey = hStart; *keys; keys++)
164 res = RegOpenKey (hTmp, *keys, &hKey);
166 if (hTmp != HKEY_LOCAL_MACHINE)
169 if (res != ERROR_SUCCESS)
175 /* Return the "mingw root" as derived from the mingw uninstall information. */
177 mingw_rootify (const char *executable)
181 char *namebuf, *foundbuf;
185 /* Open the uninstall "directory". */
186 hKey = openkey (HKEY_LOCAL_MACHINE, mingw_keys);
192 /* Need to enumerate all of the keys here looking for one the most recent
194 if (RegQueryInfoKey (hKey, NULL, NULL, NULL, NULL, &maxlen, NULL, NULL,
195 NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
200 namebuf = XNEWVEC (char, ++maxlen);
201 foundbuf = XNEWVEC (char, maxlen);
203 if (!namebuf || !foundbuf)
213 /* Look through all of the keys for one that begins with Minimal GNU...
214 Try to get the latest version by doing a string compare although that
215 string never really works with version number sorting. */
216 for (i = 0; RegEnumKey (hKey, i, namebuf, maxlen) == ERROR_SUCCESS; i++)
218 int match = strcasecmp (namebuf, MINGW_NAME);
221 if (match > 0 && strncasecmp (namebuf, MINGW_NAME, MINGW_NAME_LEN) > 0)
223 if (strcasecmp (namebuf, foundbuf) > 0)
224 strcpy (foundbuf, namebuf);
228 /* If foundbuf is empty, we didn't find anything. Punt. */
236 /* Open the key that we wanted */
237 res = RegOpenKey (hKey, foundbuf, &hTmp);
241 /* Don't know why this would fail, but you gotta check */
242 if (res != ERROR_SUCCESS)
246 /* Get the length of the value pointed to by InstallLocation */
247 if (RegQueryValueEx (hTmp, "InstallLocation", 0, NULL, NULL,
248 &maxlen) != ERROR_SUCCESS || maxlen == 0)
254 /* Allocate space for the install location */
255 foundbuf = XNEWVEC (char, maxlen + strlen (executable));
262 /* Read the install location into the buffer */
263 res = RegQueryValueEx (hTmp, "InstallLocation", 0, NULL, (LPBYTE) foundbuf,
266 if (res != ERROR_SUCCESS)
272 /* Concatenate the install location and the executable, turn all slashes
273 to backslashes, and return that. */
274 return tack_on_executable (foundbuf, executable);
277 /* Read the install location of msys from it's installation file and
278 rootify the executable based on that. */
280 msys_rootify (const char *executable)
283 size_t execlen = strlen (executable) + 1;
288 buf = XNEWVEC (char, bufsize + execlen);
291 res = GetPrivateProfileString ("InstallSettings", "InstallPath", NULL,
292 buf, bufsize, "msys.ini");
295 if (strlen (buf) < bufsize)
308 return tack_on_executable (buf, executable);
317 /* Return a Windows command-line from ARGV. It is the caller's
318 responsibility to free the string returned. */
321 argv_to_cmdline (char *const *argv)
329 for (i = 0; argv[i]; i++)
331 /* We quote every last argument. This simplifies the problem;
332 we need only escape embedded double-quotes and immediately
333 preceeding backslash characters. A sequence of backslach characters
334 that is not follwed by a double quote character will not be
336 for (j = 0; argv[i][j]; j++)
338 if (argv[i][j] == '"')
340 /* Escape preceeding backslashes. */
341 for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
343 /* Escape the qote character. */
347 /* Trailing backslashes also need to be escaped because they will be
348 followed by the terminating quote. */
349 for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
352 cmdline_len += 3; /* for leading and trailing quotes and space */
354 cmdline = xmalloc (cmdline_len);
356 for (i = 0; argv[i]; i++)
359 for (j = 0; argv[i][j]; j++)
361 if (argv[i][j] == '"')
363 for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
369 for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
378 static const char *const
386 static const char *const
392 /* Returns the full path to PROGRAM. If SEARCH is true, look for
393 PROGRAM in each directory in PATH. */
396 find_executable (const char *program, BOOL search)
398 char *full_executable;
401 const char *path = 0;
402 const char *const *ext;
404 size_t proglen = strlen (program);
405 int has_extension = !!strchr (program, '.');
406 int has_slash = (strchr (program, '/') || strchr (program, '\\'));
413 path = getenv ("PATH");
418 for (p = path; *p; p = q)
421 while (*q != ';' && *q != '\0')
423 if ((size_t)(q - p) > fe_len)
428 fe_len = fe_len + 1 + proglen + (has_extension ? 1 : 5);
429 full_executable = xmalloc (fe_len);
435 while (*q != ';' && *q != '\0')
439 memcpy (e, p, q - p);
448 for (e = full_executable; *e; e++)
452 /* At this point, e points to the terminating NUL character for
454 for (ext = has_extension ? no_suffixes : std_suffixes; *ext; ext++)
456 /* Remove any current extension. */
458 /* Add the new one. */
459 strcat (full_executable, *ext);
461 /* Attempt to open this file. */
462 h = CreateFile (full_executable, GENERIC_READ,
463 FILE_SHARE_READ | FILE_SHARE_WRITE,
464 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
465 if (h != INVALID_HANDLE_VALUE)
471 free (full_executable);
476 return full_executable;
479 /* Low-level process creation function. */
482 win32_spawn (const char *executable,
485 DWORD dwCreationFlags,
487 LPPROCESS_INFORMATION pi)
489 char *full_executable;
492 full_executable = NULL;
495 full_executable = find_executable (executable, search);
496 if (!full_executable)
498 cmdline = argv_to_cmdline (argv);
502 /* Create the child process. */
503 if (!CreateProcess (full_executable, cmdline,
504 /*lpProcessAttributes=*/NULL,
505 /*lpThreadAttributes=*/NULL,
506 /*bInheritHandles=*/TRUE,
508 /*lpEnvironment=*/NULL,
509 /*lpCurrentDirectory=*/NULL,
513 free (full_executable);
518 CloseHandle (pi->hThread);
519 free (full_executable);
521 return (long) pi->hProcess;
527 free (full_executable);
532 spawn_script (const char *executable, char *const *argv,
533 DWORD dwCreationFlags,
535 LPPROCESS_INFORMATION pi)
538 int save_errno = errno;
539 int fd = _open (executable, _O_RDONLY);
543 char buf[MAX_PATH + 5];
544 int len = _read (fd, buf, sizeof (buf) - 1);
550 eol = strchr (buf, '\n');
551 if (eol && strncmp (buf, "#!", 2) == 0)
554 const char ** avhere = (const char **) --argv;
557 while (*--eol == '\r' || *eol == ' ' || *eol == '\t');
558 for (executable1 = buf + 2; *executable1 == ' ' || *executable1 == '\t'; executable1++)
561 backslashify (executable1);
562 *avhere = executable1;
563 #ifndef USE_MINGW_MSYS
564 executable = strrchr (executable1, '\\') + 1;
566 executable = executable1;
567 pid = win32_spawn (executable, TRUE, argv,
568 dwCreationFlags, si, pi);
570 if (strchr (executable1, '\\') == NULL)
571 pid = win32_spawn (executable1, TRUE, argv,
572 dwCreationFlags, si, pi);
573 else if (executable1[0] != '\\')
574 pid = win32_spawn (executable1, FALSE, argv,
575 dwCreationFlags, si, pi);
578 const char *newex = mingw_rootify (executable1);
580 pid = win32_spawn (newex, FALSE, argv,
581 dwCreationFlags, si, pi);
582 if (executable1 != newex)
583 free ((char *) newex);
586 newex = msys_rootify (executable1);
587 if (newex != executable1)
590 pid = win32_spawn (newex, FALSE, argv,
591 dwCreationFlags, si, pi);
592 free ((char *) newex);
605 /* Execute a child. */
608 pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags,
609 const char *executable, char * const * argv,
610 int in, int out, int errdes, const char **errmsg,
615 HANDLE stdout_handle;
616 HANDLE stderr_handle;
617 DWORD dwCreationFlags;
618 OSVERSIONINFO version_info;
620 PROCESS_INFORMATION pi;
622 stdin_handle = INVALID_HANDLE_VALUE;
623 stdout_handle = INVALID_HANDLE_VALUE;
624 stderr_handle = INVALID_HANDLE_VALUE;
626 stdin_handle = (HANDLE) _get_osfhandle (in);
627 stdout_handle = (HANDLE) _get_osfhandle (out);
628 if (!(flags & PEX_STDERR_TO_STDOUT))
629 stderr_handle = (HANDLE) _get_osfhandle (errdes);
631 stderr_handle = stdout_handle;
633 /* Determine the version of Windows we are running on. */
634 version_info.dwOSVersionInfoSize = sizeof (version_info);
635 GetVersionEx (&version_info);
636 if (version_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
637 /* On Windows 95/98/ME the CREATE_NO_WINDOW flag is not
638 supported, so we cannot avoid creating a console window. */
642 HANDLE conout_handle;
644 /* Determine whether or not we have an associated console. */
645 conout_handle = CreateFile("CONOUT$",
648 /*lpSecurityAttributes=*/NULL,
650 FILE_ATTRIBUTE_NORMAL,
651 /*hTemplateFile=*/NULL);
652 if (conout_handle == INVALID_HANDLE_VALUE)
653 /* There is no console associated with this process. Since
654 the child is a console process, the OS would normally
655 create a new console Window for the child. Since we'll be
656 redirecting the child's standard streams, we do not need
657 the console window. */
658 dwCreationFlags = CREATE_NO_WINDOW;
661 /* There is a console associated with the process, so the OS
662 will not create a new console. And, if we use
663 CREATE_NO_WINDOW in this situation, the child will have
664 no associated console. Therefore, if the child's
665 standard streams are connected to the console, the output
666 will be discarded. */
667 CloseHandle(conout_handle);
672 /* Since the child will be a console process, it will, by default,
673 connect standard input/output to its console. However, we want
674 the child to use the handles specifically designated above. In
675 addition, if there is no console (such as when we are running in
676 a Cygwin X window), then we must redirect the child's
677 input/output, as there is no console for the child to use. */
678 memset (&si, 0, sizeof (si));
680 si.dwFlags = STARTF_USESTDHANDLES;
681 si.hStdInput = stdin_handle;
682 si.hStdOutput = stdout_handle;
683 si.hStdError = stderr_handle;
685 /* Create the child process. */
686 pid = win32_spawn (executable, (flags & PEX_SEARCH) != 0,
687 argv, dwCreationFlags, &si, &pi);
689 pid = spawn_script (executable, argv, dwCreationFlags, &si, &pi);
693 *errmsg = "CreateProcess";
696 /* Close the standard output and standard error handles in the
698 if (out != STDOUT_FILENO)
699 obj->funcs->close (obj, out);
700 if (errdes != STDERR_FILENO)
701 obj->funcs->close (obj, errdes);
706 /* Wait for a child process to complete. MS CRTDLL doesn't return
707 enough information in status to decide if the child exited due to a
708 signal or not, rather it simply returns an integer with the exit
709 code of the child; eg., if the child exited with an abort() call
710 and didn't have a handler for SIGABRT, it simply returns with
711 status == 3. We fix the status code to conform to the usual WIF*
712 macros. Note that WIFSIGNALED will never be true under CRTDLL. */
715 pex_win32_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, long pid,
716 int *status, struct pex_time *time, int done ATTRIBUTE_UNUSED,
717 const char **errmsg, int *err)
723 memset (time, 0, sizeof *time);
727 /* FIXME: If done is non-zero, we should probably try to kill the
729 if (WaitForSingleObject (h, INFINITE) != WAIT_OBJECT_0)
733 *errmsg = "WaitForSingleObject";
737 GetExitCodeProcess (h, &termstat);
740 /* A value of 3 indicates that the child caught a signal, but not
741 which one. Since only SIGABRT, SIGFPE and SIGINT do anything, we
746 *status = (termstat & 0xff) << 8;
754 pex_win32_pipe (struct pex_obj *obj ATTRIBUTE_UNUSED, int *p,
757 return _pipe (p, 256, binary ? _O_BINARY : _O_TEXT);
760 /* Get a FILE pointer to read from a file descriptor. */
763 pex_win32_fdopenr (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
766 return fdopen (fd, binary ? "rb" : "r");
773 main (int argc ATTRIBUTE_UNUSED, char **argv)
778 printf ("%ld\n", pex_win32_exec_child (NULL, PEX_SEARCH, argv[0], argv, 0, 1, 2, &errmsg, &err));