Partial fix for too large arrays.
[official-gcc.git] / libiberty / pex-win32.c
blob10262fbfeeddd66d3b9c393552967664437fda47
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 #ifdef HAVE_STDLIB_H
25 #include <stdlib.h>
26 #endif
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
37 #include <process.h>
38 #include <io.h>
39 #include <fcntl.h>
40 #include <signal.h>
41 #include <sys/stat.h>
43 /* mingw32 headers may not define the following. */
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
52 # define WAIT_CHILD 0
53 # define WAIT_GRANDCHILD 1
54 #endif
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. */
59 static const char * const *
60 fix_argv (char * const *argvec)
62 char **argv;
63 int i;
64 char *command0;
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')
72 for (i = 1; argvec[i] != NULL; i++)
73 if (strpbrk (argvec[i], "\" \t") != NULL)
74 break;
76 if (argvec[i] == NULL)
77 return (const char * const *) argvec;
80 for (i = 0; argvec[i] != NULL; i++)
82 argv = XNEWVEC (char *, i + 1);
83 for (i = 0; argvec[i] != NULL; i++)
84 argv[i] = xstrdup (argvec[i]);
85 argv[i] = NULL;
87 /* Ensure that the executable pathname uses Win32 backslashes. This
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++)
94 if (*command0 == '/')
95 *command0 = '\\';
97 for (i = 1; argv[i] != 0; i++)
99 int len, j;
100 char *temp, *newtemp;
102 temp = argv[i];
103 len = strlen (temp);
104 for (j = 0; j < len; j++)
106 if (temp[j] == '"')
108 newtemp = XNEWVEC (char, len + 2);
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++;
119 if (argv[i] != temp)
121 free (argv[i]);
122 argv[i] = temp;
126 for (i = 0; argv[i] != 0; i++)
128 if (strpbrk (argv[i], " \t"))
130 int len, trailing_backslash;
131 char *temp;
133 len = strlen (argv[i]);
134 trailing_backslash = 0;
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
144 && argv[i][len-1] == '\\'
145 && argv[i][len-2] != '\\')
147 trailing_backslash = 1;
148 ++len; /* to escape the final backslash. */
151 len += 2; /* and for the enclosing quotes. */
153 temp = XNEWVEC (char, len + 1);
154 temp[0] = '"';
155 strcpy (temp + 1, argv[i]);
156 if (trailing_backslash)
157 temp[len - 2] = '\\';
158 temp[len - 1] = '"';
159 temp[len] = '\0';
161 free (argv[i]);
162 argv[i] = temp;
166 return (const char * const *) argv;
169 static int pex_win32_open_read (struct pex_obj *, const char *, int);
170 static int pex_win32_open_write (struct pex_obj *, const char *, int);
171 static long pex_win32_exec_child (struct pex_obj *, int, const char *,
172 char * const *, int, int, int,
173 const char **, int *);
174 static int pex_win32_close (struct pex_obj *, int);
175 static int pex_win32_wait (struct pex_obj *, long, int *,
176 struct pex_time *, int, const char **, int *);
177 static int pex_win32_pipe (struct pex_obj *, int *, int);
178 static FILE *pex_win32_fdopenr (struct pex_obj *, int, int);
180 /* The list of functions we pass to the common routines. */
182 const struct pex_funcs funcs =
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 */
194 /* Return a newly initialized pex_obj structure. */
196 struct pex_obj *
197 pex_init (int flags, const char *pname, const char *tempbase)
199 return pex_init_common (flags, pname, tempbase, &funcs);
202 /* Open a file for reading. */
204 static int
205 pex_win32_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
206 int binary)
208 return _open (name, _O_RDONLY | (binary ? _O_BINARY : _O_TEXT));
211 /* Open a file for writing. */
213 static int
214 pex_win32_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
215 int binary)
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);
225 /* Close a file. */
227 static int
228 pex_win32_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd)
230 return _close (fd);
233 /* Execute a child. */
235 static long
236 pex_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)
241 int org_in, org_out, org_errdes;
242 long pid;
244 org_in = -1;
245 org_out = -1;
246 org_errdes = -1;
248 if (in != STDIN_FILE_NO)
250 org_in = _dup (STDIN_FILE_NO);
251 if (org_in < 0)
253 *err = errno;
254 *errmsg = "_dup";
255 return -1;
257 if (_dup2 (in, STDIN_FILE_NO) < 0)
259 *err = errno;
260 *errmsg = "_dup2";
261 return -1;
263 if (_close (in) < 0)
265 *err = errno;
266 *errmsg = "_close";
267 return -1;
271 if (out != STDOUT_FILE_NO)
273 org_out = _dup (STDOUT_FILE_NO);
274 if (org_out < 0)
276 *err = errno;
277 *errmsg = "_dup";
278 return -1;
280 if (_dup2 (out, STDOUT_FILE_NO) < 0)
282 *err = errno;
283 *errmsg = "_dup2";
284 return -1;
286 if (_close (out) < 0)
288 *err = errno;
289 *errmsg = "_close";
290 return -1;
294 if (errdes != STDERR_FILE_NO
295 || (flags & PEX_STDERR_TO_STDOUT) != 0)
297 org_errdes = _dup (STDERR_FILE_NO);
298 if (org_errdes < 0)
300 *err = errno;
301 *errmsg = "_dup";
302 return -1;
304 if (_dup2 ((flags & PEX_STDERR_TO_STDOUT) != 0 ? STDOUT_FILE_NO : errdes,
305 STDERR_FILE_NO) < 0)
307 *err = errno;
308 *errmsg = "_dup2";
309 return -1;
311 if (errdes != STDERR_FILE_NO)
313 if (_close (errdes) < 0)
315 *err = errno;
316 *errmsg = "_close";
317 return -1;
322 pid = (((flags & PEX_SEARCH) != 0 ? _spawnvp : _spawnv)
323 (_P_NOWAIT, executable, fix_argv (argv)));
325 if (pid == -1)
327 *err = errno;
328 *errmsg = ((flags & PEX_SEARCH) != 0) ? "_spawnvp" : "_spawnv";
331 if (in != STDIN_FILE_NO)
333 if (_dup2 (org_in, STDIN_FILE_NO) < 0)
335 *err = errno;
336 *errmsg = "_dup2";
337 return -1;
339 if (_close (org_in) < 0)
341 *err = errno;
342 *errmsg = "_close";
343 return -1;
347 if (out != STDOUT_FILE_NO)
349 if (_dup2 (org_out, STDOUT_FILE_NO) < 0)
351 *err = errno;
352 *errmsg = "_dup2";
353 return -1;
355 if (_close (org_out) < 0)
357 *err = errno;
358 *errmsg = "_close";
359 return -1;
363 if (errdes != STDERR_FILE_NO
364 || (flags & PEX_STDERR_TO_STDOUT) != 0)
366 if (_dup2 (org_errdes, STDERR_FILE_NO) < 0)
368 *err = errno;
369 *errmsg = "_dup2";
370 return -1;
372 if (_close (org_errdes) < 0)
374 *err = errno;
375 *errmsg = "_close";
376 return -1;
380 return pid;
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. */
391 static int
392 pex_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)
396 int termstat;
398 if (time != NULL)
399 memset (time, 0, sizeof *time);
401 /* FIXME: If done is non-zero, we should probably try to kill the
402 process. */
404 if (_cwait (&termstat, pid, WAIT_CHILD) < 0)
406 *err = errno;
407 *errmsg = "_cwait";
408 return -1;
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. */
416 if (termstat == 3)
417 *status = SIGABRT;
418 else
419 *status = ((termstat & 0xff) << 8);
421 return 0;
424 /* Create a pipe. */
426 static int
427 pex_win32_pipe (struct pex_obj *obj ATTRIBUTE_UNUSED, int *p,
428 int binary)
430 return _pipe (p, 256, binary ? _O_BINARY : _O_TEXT);
433 /* Get a FILE pointer to read from a file descriptor. */
435 static FILE *
436 pex_win32_fdopenr (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
437 int binary)
439 return fdopen (fd, binary ? "rb" : "r");