PR binutils/1437
[deliverable/binutils-gdb.git] / libiberty / pex-win32.c
CommitLineData
5a17353c
DD
1/* Utilities to execute a program in a subprocess (possibly linked by pipes
2 with other subprocesses), and wait for it. Generic Win32 specialization.
1e45deed 3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
5a17353c
DD
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,
979c05d3
NC
19write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20Boston, MA 02110-1301, USA. */
5a17353c
DD
21
22#include "pex-common.h"
23
f59e96e0
DD
24#include <windows.h>
25
b109e79a
ILT
26#ifdef HAVE_STDLIB_H
27#include <stdlib.h>
28#endif
5a17353c
DD
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 <process.h>
40#include <io.h>
41#include <fcntl.h>
42#include <signal.h>
b109e79a 43#include <sys/stat.h>
5a17353c
DD
44
45/* mingw32 headers may not define the following. */
46
47#ifndef _P_WAIT
48# define _P_WAIT 0
49# define _P_NOWAIT 1
50# define _P_OVERLAY 2
51# define _P_NOWAITO 3
52# define _P_DETACH 4
53
54# define WAIT_CHILD 0
55# define WAIT_GRANDCHILD 1
56#endif
57
f59e96e0
DD
58#define MINGW_NAME "Minimalist GNU for Windows"
59#define MINGW_NAME_LEN (sizeof(MINGW_NAME) - 1)
60
61/* Ensure that the executable pathname uses Win32 backslashes. This
62 is not necessary on NT, but on W9x, forward slashes causes
63 failure of spawn* and exec* functions (and probably any function
64 that calls CreateProcess) *iff* the executable pathname (argv[0])
65 is a quoted string. And quoting is necessary in case a pathname
66 contains embedded white space. You can't win. */
67static void
68backslashify (char *s)
69{
70 while ((s = strchr (s, '/')) != NULL)
71 *s = '\\';
72 return;
73}
74
5a17353c
DD
75/* This is a kludge to get around the Microsoft C spawn functions' propensity
76 to remove the outermost set of double quotes from all arguments. */
77
78static const char * const *
b109e79a 79fix_argv (char * const *argvec)
5a17353c 80{
b109e79a 81 char **argv;
5a17353c 82 int i;
b109e79a
ILT
83 char *command0;
84
85 /* See whether we need to change anything. */
86 for (command0 = argvec[0]; *command0 != '\0'; command0++)
87 if (*command0 == '/')
88 break;
89 if (*command0 == '\0')
90 {
91 for (i = 1; argvec[i] != NULL; i++)
92 if (strpbrk (argvec[i], "\" \t") != NULL)
93 break;
94
95 if (argvec[i] == NULL)
96 return (const char * const *) argvec;
97 }
98
99 for (i = 0; argvec[i] != NULL; i++)
100 ;
f59e96e0
DD
101 argv = XNEWVEC (char *, i + 2);
102
103 argv++; /* Leave space at the beginning of argv
104 for potential #! handling */
105
b109e79a
ILT
106 for (i = 0; argvec[i] != NULL; i++)
107 argv[i] = xstrdup (argvec[i]);
108 argv[i] = NULL;
5a17353c 109
f59e96e0 110 backslashify (argv[0]);
b109e79a
ILT
111
112 for (i = 1; argv[i] != 0; i++)
5a17353c
DD
113 {
114 int len, j;
115 char *temp, *newtemp;
116
b109e79a 117 temp = argv[i];
5a17353c
DD
118 len = strlen (temp);
119 for (j = 0; j < len; j++)
120 {
121 if (temp[j] == '"')
122 {
abf6a75b 123 newtemp = XNEWVEC (char, len + 2);
5a17353c
DD
124 strncpy (newtemp, temp, j);
125 newtemp [j] = '\\';
126 strncpy (&newtemp [j+1], &temp [j], len-j);
127 newtemp [len+1] = 0;
128 temp = newtemp;
129 len++;
130 j++;
131 }
132 }
133
b109e79a
ILT
134 if (argv[i] != temp)
135 {
136 free (argv[i]);
137 argv[i] = temp;
138 }
139 }
5a17353c 140
b109e79a 141 for (i = 0; argv[i] != 0; i++)
5a17353c 142 {
b109e79a 143 if (strpbrk (argv[i], " \t"))
5a17353c
DD
144 {
145 int len, trailing_backslash;
146 char *temp;
147
b109e79a 148 len = strlen (argv[i]);
5a17353c
DD
149 trailing_backslash = 0;
150
151 /* There is an added complication when an arg with embedded white
152 space ends in a backslash (such as in the case of -iprefix arg
153 passed to cpp). The resulting quoted strings gets misinterpreted
154 by the command interpreter -- it thinks that the ending quote
f59e96e0 155 is escaped by the trailing backslash and things get confused.
5a17353c
DD
156 We handle this case by escaping the trailing backslash, provided
157 it was not escaped in the first place. */
f59e96e0
DD
158 if (len > 1
159 && argv[i][len-1] == '\\'
b109e79a 160 && argv[i][len-2] != '\\')
5a17353c
DD
161 {
162 trailing_backslash = 1;
163 ++len; /* to escape the final backslash. */
164 }
165
166 len += 2; /* and for the enclosing quotes. */
167
abf6a75b 168 temp = XNEWVEC (char, len + 1);
5a17353c 169 temp[0] = '"';
b109e79a 170 strcpy (temp + 1, argv[i]);
5a17353c 171 if (trailing_backslash)
b109e79a
ILT
172 temp[len - 2] = '\\';
173 temp[len - 1] = '"';
5a17353c
DD
174 temp[len] = '\0';
175
b109e79a
ILT
176 free (argv[i]);
177 argv[i] = temp;
5a17353c
DD
178 }
179 }
180
b109e79a 181 return (const char * const *) argv;
5a17353c
DD
182}
183
b109e79a
ILT
184static int pex_win32_open_read (struct pex_obj *, const char *, int);
185static int pex_win32_open_write (struct pex_obj *, const char *, int);
186static long pex_win32_exec_child (struct pex_obj *, int, const char *,
187 char * const *, int, int, int,
188 const char **, int *);
189static int pex_win32_close (struct pex_obj *, int);
190static int pex_win32_wait (struct pex_obj *, long, int *,
191 struct pex_time *, int, const char **, int *);
192static int pex_win32_pipe (struct pex_obj *, int *, int);
193static FILE *pex_win32_fdopenr (struct pex_obj *, int, int);
194
195/* The list of functions we pass to the common routines. */
196
197const struct pex_funcs funcs =
5a17353c 198{
b109e79a
ILT
199 pex_win32_open_read,
200 pex_win32_open_write,
201 pex_win32_exec_child,
202 pex_win32_close,
203 pex_win32_wait,
204 pex_win32_pipe,
205 pex_win32_fdopenr,
206 NULL /* cleanup */
207};
208
209/* Return a newly initialized pex_obj structure. */
210
211struct pex_obj *
212pex_init (int flags, const char *pname, const char *tempbase)
213{
214 return pex_init_common (flags, pname, tempbase, &funcs);
215}
216
217/* Open a file for reading. */
218
219static int
220pex_win32_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
221 int binary)
222{
223 return _open (name, _O_RDONLY | (binary ? _O_BINARY : _O_TEXT));
224}
225
226/* Open a file for writing. */
227
228static int
229pex_win32_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
230 int binary)
231{
232 /* Note that we can't use O_EXCL here because gcc may have already
233 created the temporary file via make_temp_file. */
234 return _open (name,
235 (_O_WRONLY | _O_CREAT | _O_TRUNC
236 | (binary ? _O_BINARY : _O_TEXT)),
237 _S_IREAD | _S_IWRITE);
238}
239
240/* Close a file. */
241
242static int
243pex_win32_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd)
244{
245 return _close (fd);
246}
247
f59e96e0
DD
248#ifdef USE_MINGW_MSYS
249static const char *mingw_keys[] = {"SOFTWARE", "Microsoft", "Windows", "CurrentVersion", "Uninstall", NULL};
250
251/* Tack the executable on the end of a (possibly slash terminated) buffer
252 and convert everything to \. */
253static const char *
254tack_on_executable (char *buf, const char *executable)
255{
256 char *p = strchr (buf, '\0');
257 if (p > buf && (p[-1] == '\\' || p[-1] == '/'))
258 p[-1] = '\0';
259 backslashify (strcat (buf, executable));
260 return buf;
261}
262
263/* Walk down a registry hierarchy until the end. Return the key. */
264static HKEY
265openkey (HKEY hStart, const char *keys[])
266{
267 HKEY hKey, hTmp;
268 for (hKey = hStart; *keys; keys++)
269 {
270 LONG res;
271 hTmp = hKey;
272 res = RegOpenKey (hTmp, *keys, &hKey);
273
274 if (hTmp != HKEY_LOCAL_MACHINE)
275 RegCloseKey (hTmp);
276
277 if (res != ERROR_SUCCESS)
278 return NULL;
279 }
280 return hKey;
281}
282
283/* Return the "mingw root" as derived from the mingw uninstall information. */
284static const char *
285mingw_rootify (const char *executable)
286{
287 HKEY hKey, hTmp;
288 DWORD maxlen;
289 char *namebuf, *foundbuf;
290 DWORD i;
291 LONG res;
292
293 /* Open the uninstall "directory". */
294 hKey = openkey (HKEY_LOCAL_MACHINE, mingw_keys);
295
296 /* Not found. */
297 if (!hKey)
298 return executable;
299
300 /* Need to enumerate all of the keys here looking for one the most recent
301 one for MinGW. */
302 if (RegQueryInfoKey (hKey, NULL, NULL, NULL, NULL, &maxlen, NULL, NULL,
303 NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
304 {
305 RegCloseKey (hKey);
306 return executable;
307 }
308 namebuf = XNEWVEC (char, ++maxlen);
309 foundbuf = XNEWVEC (char, maxlen);
310 foundbuf[0] = '\0';
311 if (!namebuf || !foundbuf)
312 {
313 RegCloseKey (hKey);
314 if (namebuf)
315 free (namebuf);
316 if (foundbuf)
317 free (foundbuf);
318 return executable;
319 }
320
321 /* Look through all of the keys for one that begins with Minimal GNU...
322 Try to get the latest version by doing a string compare although that
323 string never really works with version number sorting. */
324 for (i = 0; RegEnumKey (hKey, i, namebuf, maxlen) == ERROR_SUCCESS; i++)
325 {
326 int match = strcasecmp (namebuf, MINGW_NAME);
327 if (match < 0)
328 continue;
329 if (match > 0 && strncasecmp (namebuf, MINGW_NAME, MINGW_NAME_LEN) > 0)
330 continue;
331 if (strcasecmp (namebuf, foundbuf) > 0)
332 strcpy (foundbuf, namebuf);
333 }
334 free (namebuf);
335
336 /* If foundbuf is empty, we didn't find anything. Punt. */
337 if (!foundbuf[0])
338 {
339 free (foundbuf);
340 RegCloseKey (hKey);
341 return executable;
342 }
343
344 /* Open the key that we wanted */
345 res = RegOpenKey (hKey, foundbuf, &hTmp);
346 RegCloseKey (hKey);
347 free (foundbuf);
348
349 /* Don't know why this would fail, but you gotta check */
350 if (res != ERROR_SUCCESS)
351 return executable;
352
353 maxlen = 0;
354 /* Get the length of the value pointed to by InstallLocation */
355 if (RegQueryValueEx (hTmp, "InstallLocation", 0, NULL, NULL,
356 &maxlen) != ERROR_SUCCESS || maxlen == 0)
357 {
358 RegCloseKey (hTmp);
359 return executable;
360 }
361
362 /* Allocate space for the install location */
363 foundbuf = XNEWVEC (char, maxlen + strlen (executable));
364 if (!foundbuf)
365 {
366 free (foundbuf);
367 RegCloseKey (hTmp);
368 }
369
370 /* Read the install location into the buffer */
371 res = RegQueryValueEx (hTmp, "InstallLocation", 0, NULL, (LPBYTE) foundbuf,
372 &maxlen);
373 RegCloseKey (hTmp);
374 if (res != ERROR_SUCCESS)
375 {
376 free (foundbuf);
377 return executable;
378 }
379
380 /* Concatenate the install location and the executable, turn all slashes
381 to backslashes, and return that. */
382 return tack_on_executable (foundbuf, executable);
383}
384
385/* Read the install location of msys from it's installation file and
386 rootify the executable based on that. */
387static const char *
388msys_rootify (const char *executable)
389{
390 size_t bufsize = 64;
391 size_t execlen = strlen (executable) + 1;
392 char *buf;
393 DWORD res = 0;
394 for (;;)
395 {
396 buf = XNEWVEC (char, bufsize + execlen);
397 if (!buf)
398 break;
399 res = GetPrivateProfileString ("InstallSettings", "InstallPath", NULL,
400 buf, bufsize, "msys.ini");
401 if (!res)
402 break;
403 if (strlen (buf) < bufsize)
404 break;
405 res = 0;
406 free (buf);
407 bufsize *= 2;
408 if (bufsize > 65536)
409 {
410 buf = NULL;
411 break;
412 }
413 }
414
415 if (res)
416 return tack_on_executable (buf, executable);
417
418 /* failed */
419 if (buf)
420 free (buf);
421 return executable;
422}
423#endif
424
425static long
426spawn_script (const char *executable, const char * const * argv)
427{
428 int pid = -1;
429 int save_errno = errno;
430 int fd = _open (executable, _O_RDONLY);
431
432 if (fd >= 0)
433 {
434 char buf[MAX_PATH + 5];
435 int len = _read (fd, buf, sizeof (buf) - 1);
436 _close (fd);
437 if (len > 3)
438 {
439 char *eol;
440 buf[len] = '\0';
441 eol = strchr (buf, '\n');
442 if (eol && strncmp (buf, "#!", 2) == 0)
443 {
444 char *executable1;
445 const char ** avhere = (const char **) --argv;
446 do
447 *eol = '\0';
448 while (*--eol == '\r' || *eol == ' ' || *eol == '\t');
449 for (executable1 = buf + 2; *executable1 == ' ' || *executable1 == '\t'; executable1++)
450 continue;
451
452 backslashify (executable1);
453 *avhere = executable1;
454#ifndef USE_MINGW_MSYS
455 executable = strrchr (executable1, '\\') + 1;
456 if (!executable)
457 executable = executable1;
458 pid = _spawnvp (_P_NOWAIT, executable, argv);
459#else
460 if (strchr (executable1, '\\') == NULL)
461 pid = _spawnvp (_P_NOWAIT, executable1, argv);
462 else if (executable1[0] != '\\')
463 pid = _spawnv (_P_NOWAIT, executable1, argv);
464 else
465 {
466 const char *newex = mingw_rootify (executable1);
467 *avhere = newex;
468 pid = _spawnv (_P_NOWAIT, newex, argv);
469 if (executable1 != newex)
470 free ((char *) newex);
471 if (pid < 0)
472 {
473 newex = msys_rootify (executable1);
474 if (newex != executable1)
475 {
476 *avhere = newex;
477 pid = _spawnv (_P_NOWAIT, newex, argv);
478 free ((char *) newex);
479 }
480 }
481 }
482#endif
483 }
484 }
485 }
486 if (pid < 0)
487 errno = save_errno;
488 return pid;
489}
490
b109e79a
ILT
491/* Execute a child. */
492
493static long
494pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags,
495 const char *executable, char * const * argv,
496 int in, int out, int errdes, const char **errmsg,
497 int *err)
498{
499 int org_in, org_out, org_errdes;
500 long pid;
f59e96e0 501 const char * const * newargv;
b109e79a
ILT
502
503 org_in = -1;
504 org_out = -1;
505 org_errdes = -1;
506
507 if (in != STDIN_FILE_NO)
5a17353c 508 {
b109e79a
ILT
509 org_in = _dup (STDIN_FILE_NO);
510 if (org_in < 0)
511 {
512 *err = errno;
513 *errmsg = "_dup";
514 return -1;
515 }
516 if (_dup2 (in, STDIN_FILE_NO) < 0)
517 {
518 *err = errno;
519 *errmsg = "_dup2";
520 return -1;
521 }
522 if (_close (in) < 0)
5a17353c 523 {
b109e79a
ILT
524 *err = errno;
525 *errmsg = "_close";
5a17353c
DD
526 return -1;
527 }
5a17353c 528 }
b109e79a
ILT
529
530 if (out != STDOUT_FILE_NO)
5a17353c 531 {
b109e79a
ILT
532 org_out = _dup (STDOUT_FILE_NO);
533 if (org_out < 0)
534 {
535 *err = errno;
536 *errmsg = "_dup";
537 return -1;
538 }
539 if (_dup2 (out, STDOUT_FILE_NO) < 0)
540 {
541 *err = errno;
542 *errmsg = "_dup2";
543 return -1;
544 }
545 if (_close (out) < 0)
546 {
547 *err = errno;
548 *errmsg = "_close";
549 return -1;
550 }
5a17353c
DD
551 }
552
b109e79a
ILT
553 if (errdes != STDERR_FILE_NO
554 || (flags & PEX_STDERR_TO_STDOUT) != 0)
5a17353c 555 {
b109e79a
ILT
556 org_errdes = _dup (STDERR_FILE_NO);
557 if (org_errdes < 0)
558 {
559 *err = errno;
560 *errmsg = "_dup";
561 return -1;
562 }
563 if (_dup2 ((flags & PEX_STDERR_TO_STDOUT) != 0 ? STDOUT_FILE_NO : errdes,
564 STDERR_FILE_NO) < 0)
565 {
566 *err = errno;
567 *errmsg = "_dup2";
568 return -1;
569 }
570 if (errdes != STDERR_FILE_NO)
571 {
572 if (_close (errdes) < 0)
573 {
574 *err = errno;
575 *errmsg = "_close";
576 return -1;
577 }
578 }
5a17353c
DD
579 }
580
f59e96e0 581 newargv = fix_argv (argv);
b109e79a 582 pid = (((flags & PEX_SEARCH) != 0 ? _spawnvp : _spawnv)
f59e96e0
DD
583 (_P_NOWAIT, executable, newargv));
584
585 if (pid == -1)
586 pid = spawn_script (executable, newargv);
b109e79a
ILT
587
588 if (pid == -1)
5a17353c 589 {
b109e79a
ILT
590 *err = errno;
591 *errmsg = ((flags & PEX_SEARCH) != 0) ? "_spawnvp" : "_spawnv";
5a17353c
DD
592 }
593
b109e79a 594 if (in != STDIN_FILE_NO)
5a17353c 595 {
b109e79a
ILT
596 if (_dup2 (org_in, STDIN_FILE_NO) < 0)
597 {
598 *err = errno;
599 *errmsg = "_dup2";
600 return -1;
601 }
602 if (_close (org_in) < 0)
603 {
604 *err = errno;
605 *errmsg = "_close";
606 return -1;
607 }
5a17353c
DD
608 }
609
b109e79a 610 if (out != STDOUT_FILE_NO)
5a17353c 611 {
b109e79a
ILT
612 if (_dup2 (org_out, STDOUT_FILE_NO) < 0)
613 {
614 *err = errno;
615 *errmsg = "_dup2";
616 return -1;
617 }
618 if (_close (org_out) < 0)
619 {
620 *err = errno;
621 *errmsg = "_close";
622 return -1;
623 }
5a17353c
DD
624 }
625
b109e79a
ILT
626 if (errdes != STDERR_FILE_NO
627 || (flags & PEX_STDERR_TO_STDOUT) != 0)
5a17353c 628 {
b109e79a
ILT
629 if (_dup2 (org_errdes, STDERR_FILE_NO) < 0)
630 {
631 *err = errno;
632 *errmsg = "_dup2";
633 return -1;
634 }
635 if (_close (org_errdes) < 0)
636 {
637 *err = errno;
638 *errmsg = "_close";
639 return -1;
640 }
5a17353c
DD
641 }
642
643 return pid;
644}
645
b109e79a
ILT
646/* Wait for a child process to complete. MS CRTDLL doesn't return
647 enough information in status to decide if the child exited due to a
648 signal or not, rather it simply returns an integer with the exit
649 code of the child; eg., if the child exited with an abort() call
650 and didn't have a handler for SIGABRT, it simply returns with
651 status == 3. We fix the status code to conform to the usual WIF*
652 macros. Note that WIFSIGNALED will never be true under CRTDLL. */
653
654static int
655pex_win32_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, long pid,
656 int *status, struct pex_time *time, int done ATTRIBUTE_UNUSED,
657 const char **errmsg, int *err)
5a17353c
DD
658{
659 int termstat;
660
b109e79a
ILT
661 if (time != NULL)
662 memset (time, 0, sizeof *time);
663
664 /* FIXME: If done is non-zero, we should probably try to kill the
665 process. */
666
667 if (_cwait (&termstat, pid, WAIT_CHILD) < 0)
668 {
669 *err = errno;
670 *errmsg = "_cwait";
671 return -1;
672 }
5a17353c 673
b109e79a
ILT
674 /* cwait returns the child process exit code in termstat. A value
675 of 3 indicates that the child caught a signal, but not which one.
676 Since only SIGABRT, SIGFPE and SIGINT do anything, we report
677 SIGABRT. */
5a17353c 678
5a17353c
DD
679 if (termstat == 3)
680 *status = SIGABRT;
681 else
b109e79a 682 *status = ((termstat & 0xff) << 8);
5a17353c 683
b109e79a
ILT
684 return 0;
685}
686
687/* Create a pipe. */
688
689static int
690pex_win32_pipe (struct pex_obj *obj ATTRIBUTE_UNUSED, int *p,
691 int binary)
692{
693 return _pipe (p, 256, binary ? _O_BINARY : _O_TEXT);
694}
695
696/* Get a FILE pointer to read from a file descriptor. */
697
698static FILE *
699pex_win32_fdopenr (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
700 int binary)
701{
702 return fdopen (fd, binary ? "rb" : "r");
5a17353c 703}
f59e96e0
DD
704
705#ifdef MAIN
706#include <stdio.h>
707
708int
709main (int argc ATTRIBUTE_UNUSED, char **argv)
710{
711 char const *errmsg;
712 int err;
713 argv++;
714 printf ("%ld\n", pex_win32_exec_child (NULL, PEX_SEARCH, argv[0], argv, 0, 1, 2, &errmsg, &err));
715 exit (0);
716}
717#endif
This page took 0.155652 seconds and 4 git commands to generate.