]> git.ipfire.org Git - thirdparty/gcc.git/blame - libiberty/pex-win32.c
Daily bump.
[thirdparty/gcc.git] / libiberty / pex-win32.c
CommitLineData
55d0e5e0
ZW
1/* Utilities to execute a program in a subprocess (possibly linked by pipes
2 with other subprocesses), and wait for it. Generic Win32 specialization.
885f2199 3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
55d0e5e0
ZW
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,
ee58dffd
NC
19write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20Boston, MA 02110-1301, USA. */
55d0e5e0
ZW
21
22#include "pex-common.h"
23
a584cf65
ILT
24#ifdef HAVE_STDLIB_H
25#include <stdlib.h>
26#endif
55d0e5e0
ZW
27#ifdef HAVE_STRING_H
28#include <string.h>
29#endif
30#ifdef HAVE_UNISTD_H
31#include <unistd.h>
32#endif
33#ifdef HAVE_SYS_WAIT_H
34#include <sys/wait.h>
35#endif
36
37#include <process.h>
38#include <io.h>
39#include <fcntl.h>
40#include <signal.h>
a584cf65 41#include <sys/stat.h>
55d0e5e0
ZW
42
43/* mingw32 headers may not define the following. */
44
45#ifndef _P_WAIT
46# define _P_WAIT 0
47# define _P_NOWAIT 1
48# define _P_OVERLAY 2
49# define _P_NOWAITO 3
50# define _P_DETACH 4
51
52# define WAIT_CHILD 0
53# define WAIT_GRANDCHILD 1
54#endif
55
56/* This is a kludge to get around the Microsoft C spawn functions' propensity
57 to remove the outermost set of double quotes from all arguments. */
58
59static const char * const *
a584cf65 60fix_argv (char * const *argvec)
55d0e5e0 61{
a584cf65 62 char **argv;
55d0e5e0 63 int i;
a584cf65
ILT
64 char *command0;
65
66 /* See whether we need to change anything. */
67 for (command0 = argvec[0]; *command0 != '\0'; command0++)
68 if (*command0 == '/')
69 break;
70 if (*command0 == '\0')
71 {
72 for (i = 1; argvec[i] != NULL; i++)
73 if (strpbrk (argvec[i], "\" \t") != NULL)
74 break;
75
76 if (argvec[i] == NULL)
77 return (const char * const *) argvec;
78 }
79
80 for (i = 0; argvec[i] != NULL; i++)
81 ;
d7cf8390 82 argv = XNEWVEC (char *, i + 1);
a584cf65
ILT
83 for (i = 0; argvec[i] != NULL; i++)
84 argv[i] = xstrdup (argvec[i]);
85 argv[i] = NULL;
55d0e5e0 86
b47785f4 87 /* Ensure that the executable pathname uses Win32 backslashes. This
a584cf65
ILT
88 is not necessary on NT, but on W9x, forward slashes causes
89 failure of spawn* and exec* functions (and probably any function
90 that calls CreateProcess) *iff* the executable pathname (argv[0])
91 is a quoted string. And quoting is necessary in case a pathname
92 contains embedded white space. You can't win. */
93 for (command0 = argv[0]; *command0 != '\0'; command0++)
bacb96b2
DS
94 if (*command0 == '/')
95 *command0 = '\\';
a584cf65
ILT
96
97 for (i = 1; argv[i] != 0; i++)
55d0e5e0
ZW
98 {
99 int len, j;
100 char *temp, *newtemp;
101
a584cf65 102 temp = argv[i];
55d0e5e0
ZW
103 len = strlen (temp);
104 for (j = 0; j < len; j++)
105 {
106 if (temp[j] == '"')
107 {
d7cf8390 108 newtemp = XNEWVEC (char, len + 2);
55d0e5e0
ZW
109 strncpy (newtemp, temp, j);
110 newtemp [j] = '\\';
111 strncpy (&newtemp [j+1], &temp [j], len-j);
112 newtemp [len+1] = 0;
113 temp = newtemp;
114 len++;
115 j++;
116 }
117 }
118
a584cf65
ILT
119 if (argv[i] != temp)
120 {
121 free (argv[i]);
122 argv[i] = temp;
123 }
124 }
55d0e5e0 125
a584cf65 126 for (i = 0; argv[i] != 0; i++)
55d0e5e0 127 {
a584cf65 128 if (strpbrk (argv[i], " \t"))
55d0e5e0
ZW
129 {
130 int len, trailing_backslash;
131 char *temp;
132
a584cf65 133 len = strlen (argv[i]);
55d0e5e0
ZW
134 trailing_backslash = 0;
135
136 /* There is an added complication when an arg with embedded white
137 space ends in a backslash (such as in the case of -iprefix arg
138 passed to cpp). The resulting quoted strings gets misinterpreted
139 by the command interpreter -- it thinks that the ending quote
140 is escaped by the trailing backslash and things get confused.
141 We handle this case by escaping the trailing backslash, provided
142 it was not escaped in the first place. */
143 if (len > 1
a584cf65
ILT
144 && argv[i][len-1] == '\\'
145 && argv[i][len-2] != '\\')
55d0e5e0
ZW
146 {
147 trailing_backslash = 1;
148 ++len; /* to escape the final backslash. */
149 }
150
151 len += 2; /* and for the enclosing quotes. */
152
d7cf8390 153 temp = XNEWVEC (char, len + 1);
55d0e5e0 154 temp[0] = '"';
a584cf65 155 strcpy (temp + 1, argv[i]);
55d0e5e0 156 if (trailing_backslash)
a584cf65
ILT
157 temp[len - 2] = '\\';
158 temp[len - 1] = '"';
55d0e5e0
ZW
159 temp[len] = '\0';
160
a584cf65
ILT
161 free (argv[i]);
162 argv[i] = temp;
55d0e5e0
ZW
163 }
164 }
165
a584cf65 166 return (const char * const *) argv;
55d0e5e0
ZW
167}
168
a584cf65
ILT
169static int pex_win32_open_read (struct pex_obj *, const char *, int);
170static int pex_win32_open_write (struct pex_obj *, const char *, int);
171static long pex_win32_exec_child (struct pex_obj *, int, const char *,
172 char * const *, int, int, int,
173 const char **, int *);
174static int pex_win32_close (struct pex_obj *, int);
175static int pex_win32_wait (struct pex_obj *, long, int *,
176 struct pex_time *, int, const char **, int *);
177static int pex_win32_pipe (struct pex_obj *, int *, int);
178static FILE *pex_win32_fdopenr (struct pex_obj *, int, int);
179
180/* The list of functions we pass to the common routines. */
181
182const struct pex_funcs funcs =
55d0e5e0 183{
a584cf65
ILT
184 pex_win32_open_read,
185 pex_win32_open_write,
186 pex_win32_exec_child,
187 pex_win32_close,
188 pex_win32_wait,
189 pex_win32_pipe,
190 pex_win32_fdopenr,
191 NULL /* cleanup */
192};
193
194/* Return a newly initialized pex_obj structure. */
195
196struct pex_obj *
197pex_init (int flags, const char *pname, const char *tempbase)
198{
199 return pex_init_common (flags, pname, tempbase, &funcs);
200}
201
202/* Open a file for reading. */
203
204static int
205pex_win32_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
206 int binary)
207{
208 return _open (name, _O_RDONLY | (binary ? _O_BINARY : _O_TEXT));
209}
210
211/* Open a file for writing. */
212
213static int
214pex_win32_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
215 int binary)
216{
217 /* Note that we can't use O_EXCL here because gcc may have already
218 created the temporary file via make_temp_file. */
219 return _open (name,
220 (_O_WRONLY | _O_CREAT | _O_TRUNC
221 | (binary ? _O_BINARY : _O_TEXT)),
222 _S_IREAD | _S_IWRITE);
223}
224
225/* Close a file. */
226
227static int
228pex_win32_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd)
229{
230 return _close (fd);
231}
232
233/* Execute a child. */
234
235static long
236pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags,
237 const char *executable, char * const * argv,
238 int in, int out, int errdes, const char **errmsg,
239 int *err)
240{
241 int org_in, org_out, org_errdes;
242 long pid;
243
244 org_in = -1;
245 org_out = -1;
246 org_errdes = -1;
247
248 if (in != STDIN_FILE_NO)
55d0e5e0 249 {
a584cf65
ILT
250 org_in = _dup (STDIN_FILE_NO);
251 if (org_in < 0)
252 {
253 *err = errno;
254 *errmsg = "_dup";
255 return -1;
256 }
257 if (_dup2 (in, STDIN_FILE_NO) < 0)
258 {
259 *err = errno;
260 *errmsg = "_dup2";
261 return -1;
262 }
263 if (_close (in) < 0)
55d0e5e0 264 {
a584cf65
ILT
265 *err = errno;
266 *errmsg = "_close";
55d0e5e0
ZW
267 return -1;
268 }
55d0e5e0 269 }
a584cf65
ILT
270
271 if (out != STDOUT_FILE_NO)
55d0e5e0 272 {
a584cf65
ILT
273 org_out = _dup (STDOUT_FILE_NO);
274 if (org_out < 0)
275 {
276 *err = errno;
277 *errmsg = "_dup";
278 return -1;
279 }
280 if (_dup2 (out, STDOUT_FILE_NO) < 0)
281 {
282 *err = errno;
283 *errmsg = "_dup2";
284 return -1;
285 }
286 if (_close (out) < 0)
287 {
288 *err = errno;
289 *errmsg = "_close";
290 return -1;
291 }
55d0e5e0
ZW
292 }
293
a584cf65
ILT
294 if (errdes != STDERR_FILE_NO
295 || (flags & PEX_STDERR_TO_STDOUT) != 0)
55d0e5e0 296 {
a584cf65
ILT
297 org_errdes = _dup (STDERR_FILE_NO);
298 if (org_errdes < 0)
299 {
300 *err = errno;
301 *errmsg = "_dup";
302 return -1;
303 }
304 if (_dup2 ((flags & PEX_STDERR_TO_STDOUT) != 0 ? STDOUT_FILE_NO : errdes,
305 STDERR_FILE_NO) < 0)
306 {
307 *err = errno;
308 *errmsg = "_dup2";
309 return -1;
310 }
311 if (errdes != STDERR_FILE_NO)
312 {
313 if (_close (errdes) < 0)
314 {
315 *err = errno;
316 *errmsg = "_close";
317 return -1;
318 }
319 }
55d0e5e0
ZW
320 }
321
a584cf65
ILT
322 pid = (((flags & PEX_SEARCH) != 0 ? _spawnvp : _spawnv)
323 (_P_NOWAIT, executable, fix_argv (argv)));
324
325 if (pid == -1)
55d0e5e0 326 {
a584cf65
ILT
327 *err = errno;
328 *errmsg = ((flags & PEX_SEARCH) != 0) ? "_spawnvp" : "_spawnv";
55d0e5e0
ZW
329 }
330
a584cf65 331 if (in != STDIN_FILE_NO)
55d0e5e0 332 {
a584cf65
ILT
333 if (_dup2 (org_in, STDIN_FILE_NO) < 0)
334 {
335 *err = errno;
336 *errmsg = "_dup2";
337 return -1;
338 }
339 if (_close (org_in) < 0)
340 {
341 *err = errno;
342 *errmsg = "_close";
343 return -1;
344 }
55d0e5e0
ZW
345 }
346
a584cf65 347 if (out != STDOUT_FILE_NO)
55d0e5e0 348 {
a584cf65
ILT
349 if (_dup2 (org_out, STDOUT_FILE_NO) < 0)
350 {
351 *err = errno;
352 *errmsg = "_dup2";
353 return -1;
354 }
355 if (_close (org_out) < 0)
356 {
357 *err = errno;
358 *errmsg = "_close";
359 return -1;
360 }
55d0e5e0
ZW
361 }
362
a584cf65
ILT
363 if (errdes != STDERR_FILE_NO
364 || (flags & PEX_STDERR_TO_STDOUT) != 0)
55d0e5e0 365 {
a584cf65
ILT
366 if (_dup2 (org_errdes, STDERR_FILE_NO) < 0)
367 {
368 *err = errno;
369 *errmsg = "_dup2";
370 return -1;
371 }
372 if (_close (org_errdes) < 0)
373 {
374 *err = errno;
375 *errmsg = "_close";
376 return -1;
377 }
55d0e5e0
ZW
378 }
379
380 return pid;
381}
382
a584cf65
ILT
383/* Wait for a child process to complete. MS CRTDLL doesn't return
384 enough information in status to decide if the child exited due to a
385 signal or not, rather it simply returns an integer with the exit
386 code of the child; eg., if the child exited with an abort() call
387 and didn't have a handler for SIGABRT, it simply returns with
388 status == 3. We fix the status code to conform to the usual WIF*
389 macros. Note that WIFSIGNALED will never be true under CRTDLL. */
390
391static int
392pex_win32_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, long pid,
393 int *status, struct pex_time *time, int done ATTRIBUTE_UNUSED,
394 const char **errmsg, int *err)
55d0e5e0
ZW
395{
396 int termstat;
397
a584cf65
ILT
398 if (time != NULL)
399 memset (time, 0, sizeof *time);
400
401 /* FIXME: If done is non-zero, we should probably try to kill the
402 process. */
403
404 if (_cwait (&termstat, pid, WAIT_CHILD) < 0)
405 {
406 *err = errno;
407 *errmsg = "_cwait";
408 return -1;
409 }
55d0e5e0 410
a584cf65
ILT
411 /* cwait returns the child process exit code in termstat. A value
412 of 3 indicates that the child caught a signal, but not which one.
413 Since only SIGABRT, SIGFPE and SIGINT do anything, we report
414 SIGABRT. */
55d0e5e0 415
55d0e5e0
ZW
416 if (termstat == 3)
417 *status = SIGABRT;
418 else
a584cf65 419 *status = ((termstat & 0xff) << 8);
55d0e5e0 420
a584cf65
ILT
421 return 0;
422}
423
424/* Create a pipe. */
425
426static int
427pex_win32_pipe (struct pex_obj *obj ATTRIBUTE_UNUSED, int *p,
428 int binary)
429{
430 return _pipe (p, 256, binary ? _O_BINARY : _O_TEXT);
431}
432
433/* Get a FILE pointer to read from a file descriptor. */
434
435static FILE *
436pex_win32_fdopenr (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
437 int binary)
438{
439 return fdopen (fd, binary ? "rb" : "r");
55d0e5e0 440}