* tree-cfg.c (make_ctrl_stmt_edges, make_exit_edges): Merge into...
[official-gcc.git] / libiberty / pex-win32.c
blob3a75c5be004dc204d780f2bccd895c11645be86c
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"
24 #include <windows.h>
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
39 #include <process.h>
40 #include <io.h>
41 #include <fcntl.h>
42 #include <signal.h>
43 #include <sys/stat.h>
44 #include <errno.h>
46 /* mingw32 headers may not define the following. */
48 #ifndef _P_WAIT
49 # define _P_WAIT 0
50 # define _P_NOWAIT 1
51 # define _P_OVERLAY 2
52 # define _P_NOWAITO 3
53 # define _P_DETACH 4
55 # define WAIT_CHILD 0
56 # define WAIT_GRANDCHILD 1
57 #endif
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. */
68 static void
69 backslashify (char *s)
71 while ((s = strchr (s, '/')) != NULL)
72 *s = '\\';
73 return;
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 =
91 pex_win32_open_read,
92 pex_win32_open_write,
93 pex_win32_exec_child,
94 pex_win32_close,
95 pex_win32_wait,
96 pex_win32_pipe,
97 pex_win32_fdopenr,
98 NULL /* cleanup */
101 /* Return a newly initialized pex_obj structure. */
103 struct pex_obj *
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. */
111 static int
112 pex_win32_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
113 int binary)
115 return _open (name, _O_RDONLY | (binary ? _O_BINARY : _O_TEXT));
118 /* Open a file for writing. */
120 static int
121 pex_win32_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
122 int binary)
124 /* Note that we can't use O_EXCL here because gcc may have already
125 created the temporary file via make_temp_file. */
126 return _open (name,
127 (_O_WRONLY | _O_CREAT | _O_TRUNC
128 | (binary ? _O_BINARY : _O_TEXT)),
129 _S_IREAD | _S_IWRITE);
132 /* Close a file. */
134 static int
135 pex_win32_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd)
137 return _close (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 \. */
145 static const char *
146 tack_on_executable (char *buf, const char *executable)
148 char *p = strchr (buf, '\0');
149 if (p > buf && (p[-1] == '\\' || p[-1] == '/'))
150 p[-1] = '\0';
151 backslashify (strcat (buf, executable));
152 return buf;
155 /* Walk down a registry hierarchy until the end. Return the key. */
156 static HKEY
157 openkey (HKEY hStart, const char *keys[])
159 HKEY hKey, hTmp;
160 for (hKey = hStart; *keys; keys++)
162 LONG res;
163 hTmp = hKey;
164 res = RegOpenKey (hTmp, *keys, &hKey);
166 if (hTmp != HKEY_LOCAL_MACHINE)
167 RegCloseKey (hTmp);
169 if (res != ERROR_SUCCESS)
170 return NULL;
172 return hKey;
175 /* Return the "mingw root" as derived from the mingw uninstall information. */
176 static const char *
177 mingw_rootify (const char *executable)
179 HKEY hKey, hTmp;
180 DWORD maxlen;
181 char *namebuf, *foundbuf;
182 DWORD i;
183 LONG res;
185 /* Open the uninstall "directory". */
186 hKey = openkey (HKEY_LOCAL_MACHINE, mingw_keys);
188 /* Not found. */
189 if (!hKey)
190 return executable;
192 /* Need to enumerate all of the keys here looking for one the most recent
193 one for MinGW. */
194 if (RegQueryInfoKey (hKey, NULL, NULL, NULL, NULL, &maxlen, NULL, NULL,
195 NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
197 RegCloseKey (hKey);
198 return executable;
200 namebuf = XNEWVEC (char, ++maxlen);
201 foundbuf = XNEWVEC (char, maxlen);
202 foundbuf[0] = '\0';
203 if (!namebuf || !foundbuf)
205 RegCloseKey (hKey);
206 if (namebuf)
207 free (namebuf);
208 if (foundbuf)
209 free (foundbuf);
210 return executable;
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);
219 if (match < 0)
220 continue;
221 if (match > 0 && strncasecmp (namebuf, MINGW_NAME, MINGW_NAME_LEN) > 0)
222 continue;
223 if (strcasecmp (namebuf, foundbuf) > 0)
224 strcpy (foundbuf, namebuf);
226 free (namebuf);
228 /* If foundbuf is empty, we didn't find anything. Punt. */
229 if (!foundbuf[0])
231 free (foundbuf);
232 RegCloseKey (hKey);
233 return executable;
236 /* Open the key that we wanted */
237 res = RegOpenKey (hKey, foundbuf, &hTmp);
238 RegCloseKey (hKey);
239 free (foundbuf);
241 /* Don't know why this would fail, but you gotta check */
242 if (res != ERROR_SUCCESS)
243 return executable;
245 maxlen = 0;
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)
250 RegCloseKey (hTmp);
251 return executable;
254 /* Allocate space for the install location */
255 foundbuf = XNEWVEC (char, maxlen + strlen (executable));
256 if (!foundbuf)
258 free (foundbuf);
259 RegCloseKey (hTmp);
262 /* Read the install location into the buffer */
263 res = RegQueryValueEx (hTmp, "InstallLocation", 0, NULL, (LPBYTE) foundbuf,
264 &maxlen);
265 RegCloseKey (hTmp);
266 if (res != ERROR_SUCCESS)
268 free (foundbuf);
269 return executable;
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. */
279 static const char *
280 msys_rootify (const char *executable)
282 size_t bufsize = 64;
283 size_t execlen = strlen (executable) + 1;
284 char *buf;
285 DWORD res = 0;
286 for (;;)
288 buf = XNEWVEC (char, bufsize + execlen);
289 if (!buf)
290 break;
291 res = GetPrivateProfileString ("InstallSettings", "InstallPath", NULL,
292 buf, bufsize, "msys.ini");
293 if (!res)
294 break;
295 if (strlen (buf) < bufsize)
296 break;
297 res = 0;
298 free (buf);
299 bufsize *= 2;
300 if (bufsize > 65536)
302 buf = NULL;
303 break;
307 if (res)
308 return tack_on_executable (buf, executable);
310 /* failed */
311 if (buf)
312 free (buf);
313 return executable;
315 #endif
317 /* Return a Windows command-line from ARGV. It is the caller's
318 responsibility to free the string returned. */
320 static char *
321 argv_to_cmdline (char *const *argv)
323 char *cmdline;
324 char *p;
325 size_t cmdline_len;
326 int i, j, k;
328 cmdline_len = 0;
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
335 escaped. */
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--)
342 cmdline_len++;
343 /* Escape the qote character. */
344 cmdline_len++;
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--)
350 cmdline_len++;
351 cmdline_len += j;
352 cmdline_len += 3; /* for leading and trailing quotes and space */
354 cmdline = xmalloc (cmdline_len);
355 p = cmdline;
356 for (i = 0; argv[i]; i++)
358 *p++ = '"';
359 for (j = 0; argv[i][j]; j++)
361 if (argv[i][j] == '"')
363 for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
364 *p++ = '\\';
365 *p++ = '\\';
367 *p++ = argv[i][j];
369 for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
370 *p++ = '\\';
371 *p++ = '"';
372 *p++ = ' ';
374 p[-1] = '\0';
375 return cmdline;
378 static const char *const
379 std_suffixes[] = {
380 ".com",
381 ".exe",
382 ".bat",
383 ".cmd",
386 static const char *const
387 no_suffixes[] = {
392 /* Returns the full path to PROGRAM. If SEARCH is true, look for
393 PROGRAM in each directory in PATH. */
395 static char *
396 find_executable (const char *program, BOOL search)
398 char *full_executable;
399 char *e;
400 size_t fe_len;
401 const char *path = 0;
402 const char *const *ext;
403 const char *p, *q;
404 size_t proglen = strlen (program);
405 int has_extension = !!strchr (program, '.');
406 int has_slash = (strchr (program, '/') || strchr (program, '\\'));
407 HANDLE h;
409 if (has_slash)
410 search = FALSE;
412 if (search)
413 path = getenv ("PATH");
414 if (!path)
415 path = "";
417 fe_len = 0;
418 for (p = path; *p; p = q)
420 q = p;
421 while (*q != ';' && *q != '\0')
422 q++;
423 if ((size_t)(q - p) > fe_len)
424 fe_len = q - p;
425 if (*q == ';')
426 q++;
428 fe_len = fe_len + 1 + proglen + (has_extension ? 1 : 5);
429 full_executable = xmalloc (fe_len);
431 p = path;
434 q = p;
435 while (*q != ';' && *q != '\0')
436 q++;
438 e = full_executable;
439 memcpy (e, p, q - p);
440 e += (q - p);
441 if (q - p)
442 *e++ = '\\';
443 strcpy (e, program);
445 if (*q == ';')
446 q++;
448 for (e = full_executable; *e; e++)
449 if (*e == '/')
450 *e = '\\';
452 /* At this point, e points to the terminating NUL character for
453 full_executable. */
454 for (ext = has_extension ? no_suffixes : std_suffixes; *ext; ext++)
456 /* Remove any current extension. */
457 *e = '\0';
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)
466 goto found;
468 p = q;
470 while (*p);
471 free (full_executable);
472 return 0;
474 found:
475 CloseHandle (h);
476 return full_executable;
479 /* Low-level process creation function. */
481 static long
482 win32_spawn (const char *executable,
483 BOOL search,
484 char *const *argv,
485 DWORD dwCreationFlags,
486 LPSTARTUPINFO si,
487 LPPROCESS_INFORMATION pi)
489 char *full_executable;
490 char *cmdline;
492 full_executable = NULL;
493 cmdline = NULL;
495 full_executable = find_executable (executable, search);
496 if (!full_executable)
497 goto error;
498 cmdline = argv_to_cmdline (argv);
499 if (!cmdline)
500 goto error;
502 /* Create the child process. */
503 if (!CreateProcess (full_executable, cmdline,
504 /*lpProcessAttributes=*/NULL,
505 /*lpThreadAttributes=*/NULL,
506 /*bInheritHandles=*/TRUE,
507 dwCreationFlags,
508 /*lpEnvironment=*/NULL,
509 /*lpCurrentDirectory=*/NULL,
511 pi))
513 free (full_executable);
514 return -1;
517 /* Clean up. */
518 CloseHandle (pi->hThread);
519 free (full_executable);
521 return (long) pi->hProcess;
523 error:
524 if (cmdline)
525 free (cmdline);
526 if (full_executable)
527 free (full_executable);
528 return -1;
531 static long
532 spawn_script (const char *executable, char *const *argv,
533 DWORD dwCreationFlags,
534 LPSTARTUPINFO si,
535 LPPROCESS_INFORMATION pi)
537 int pid = -1;
538 int save_errno = errno;
539 int fd = _open (executable, _O_RDONLY);
541 if (fd >= 0)
543 char buf[MAX_PATH + 5];
544 int len = _read (fd, buf, sizeof (buf) - 1);
545 _close (fd);
546 if (len > 3)
548 char *eol;
549 buf[len] = '\0';
550 eol = strchr (buf, '\n');
551 if (eol && strncmp (buf, "#!", 2) == 0)
553 char *executable1;
554 const char ** avhere = (const char **) --argv;
556 *eol = '\0';
557 while (*--eol == '\r' || *eol == ' ' || *eol == '\t');
558 for (executable1 = buf + 2; *executable1 == ' ' || *executable1 == '\t'; executable1++)
559 continue;
561 backslashify (executable1);
562 *avhere = executable1;
563 #ifndef USE_MINGW_MSYS
564 executable = strrchr (executable1, '\\') + 1;
565 if (!executable)
566 executable = executable1;
567 pid = win32_spawn (executable, TRUE, argv,
568 dwCreationFlags, si, pi);
569 #else
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);
576 else
578 const char *newex = mingw_rootify (executable1);
579 *avhere = newex;
580 pid = win32_spawn (newex, FALSE, argv,
581 dwCreationFlags, si, pi);
582 if (executable1 != newex)
583 free ((char *) newex);
584 if (pid < 0)
586 newex = msys_rootify (executable1);
587 if (newex != executable1)
589 *avhere = newex;
590 pid = win32_spawn (newex, FALSE, argv,
591 dwCreationFlags, si, pi);
592 free ((char *) newex);
596 #endif
600 if (pid < 0)
601 errno = save_errno;
602 return pid;
605 /* Execute a child. */
607 static long
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,
611 int *err)
613 long pid;
614 HANDLE stdin_handle;
615 HANDLE stdout_handle;
616 HANDLE stderr_handle;
617 DWORD dwCreationFlags;
618 OSVERSIONINFO version_info;
619 STARTUPINFO si;
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);
630 else
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. */
639 dwCreationFlags = 0;
640 else
642 HANDLE conout_handle;
644 /* Determine whether or not we have an associated console. */
645 conout_handle = CreateFile("CONOUT$",
646 GENERIC_WRITE,
647 FILE_SHARE_WRITE,
648 /*lpSecurityAttributes=*/NULL,
649 OPEN_EXISTING,
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;
659 else
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);
668 dwCreationFlags = 0;
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));
679 si.cb = 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);
688 if (pid == -1)
689 pid = spawn_script (executable, argv, dwCreationFlags, &si, &pi);
690 if (pid == -1)
692 *err = ENOENT;
693 *errmsg = "CreateProcess";
696 /* Close the standard output and standard error handles in the
697 parent. */
698 if (out != STDOUT_FILENO)
699 obj->funcs->close (obj, out);
700 if (errdes != STDERR_FILENO)
701 obj->funcs->close (obj, errdes);
703 return pid;
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. */
714 static int
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)
719 DWORD termstat;
720 HANDLE h;
722 if (time != NULL)
723 memset (time, 0, sizeof *time);
725 h = (HANDLE) pid;
727 /* FIXME: If done is non-zero, we should probably try to kill the
728 process. */
729 if (WaitForSingleObject (h, INFINITE) != WAIT_OBJECT_0)
731 CloseHandle (h);
732 *err = ECHILD;
733 *errmsg = "WaitForSingleObject";
734 return -1;
737 GetExitCodeProcess (h, &termstat);
738 CloseHandle (h);
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
742 report SIGABRT. */
743 if (termstat == 3)
744 *status = SIGABRT;
745 else
746 *status = (termstat & 0xff) << 8;
748 return 0;
751 /* Create a pipe. */
753 static int
754 pex_win32_pipe (struct pex_obj *obj ATTRIBUTE_UNUSED, int *p,
755 int binary)
757 return _pipe (p, 256, binary ? _O_BINARY : _O_TEXT);
760 /* Get a FILE pointer to read from a file descriptor. */
762 static FILE *
763 pex_win32_fdopenr (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
764 int binary)
766 return fdopen (fd, binary ? "rb" : "r");
769 #ifdef MAIN
770 #include <stdio.h>
773 main (int argc ATTRIBUTE_UNUSED, char **argv)
775 char const *errmsg;
776 int err;
777 argv++;
778 printf ("%ld\n", pex_win32_exec_child (NULL, PEX_SEARCH, argv[0], argv, 0, 1, 2, &errmsg, &err));
779 exit (0);
781 #endif