0
|
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, 2006
|
|
4 Free Software Foundation, Inc.
|
|
5
|
|
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.
|
|
11
|
|
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.
|
|
16
|
|
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. */
|
|
21
|
|
22 #include "pex-common.h"
|
|
23
|
|
24 #include <windows.h>
|
|
25
|
|
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
|
|
38
|
|
39 #include <assert.h>
|
|
40 #include <process.h>
|
|
41 #include <io.h>
|
|
42 #include <fcntl.h>
|
|
43 #include <signal.h>
|
|
44 #include <sys/stat.h>
|
|
45 #include <errno.h>
|
|
46 #include <ctype.h>
|
|
47
|
|
48 /* mingw32 headers may not define the following. */
|
|
49
|
|
50 #ifndef _P_WAIT
|
|
51 # define _P_WAIT 0
|
|
52 # define _P_NOWAIT 1
|
|
53 # define _P_OVERLAY 2
|
|
54 # define _P_NOWAITO 3
|
|
55 # define _P_DETACH 4
|
|
56
|
|
57 # define WAIT_CHILD 0
|
|
58 # define WAIT_GRANDCHILD 1
|
|
59 #endif
|
|
60
|
|
61 #define MINGW_NAME "Minimalist GNU for Windows"
|
|
62 #define MINGW_NAME_LEN (sizeof(MINGW_NAME) - 1)
|
|
63
|
|
64 extern char *stpcpy (char *dst, const char *src);
|
|
65
|
|
66 /* Ensure that the executable pathname uses Win32 backslashes. This
|
|
67 is not necessary on NT, but on W9x, forward slashes causes
|
|
68 failure of spawn* and exec* functions (and probably any function
|
|
69 that calls CreateProcess) *iff* the executable pathname (argv[0])
|
|
70 is a quoted string. And quoting is necessary in case a pathname
|
|
71 contains embedded white space. You can't win. */
|
|
72 static void
|
|
73 backslashify (char *s)
|
|
74 {
|
|
75 while ((s = strchr (s, '/')) != NULL)
|
|
76 *s = '\\';
|
|
77 return;
|
|
78 }
|
|
79
|
|
80 static int pex_win32_open_read (struct pex_obj *, const char *, int);
|
|
81 static int pex_win32_open_write (struct pex_obj *, const char *, int);
|
|
82 static pid_t pex_win32_exec_child (struct pex_obj *, int, const char *,
|
|
83 char * const *, char * const *,
|
|
84 int, int, int, int,
|
|
85 const char **, int *);
|
|
86 static int pex_win32_close (struct pex_obj *, int);
|
|
87 static int pex_win32_wait (struct pex_obj *, pid_t, int *,
|
|
88 struct pex_time *, int, const char **, int *);
|
|
89 static int pex_win32_pipe (struct pex_obj *, int *, int);
|
|
90 static FILE *pex_win32_fdopenr (struct pex_obj *, int, int);
|
|
91 static FILE *pex_win32_fdopenw (struct pex_obj *, int, int);
|
|
92
|
|
93 /* The list of functions we pass to the common routines. */
|
|
94
|
|
95 const struct pex_funcs funcs =
|
|
96 {
|
|
97 pex_win32_open_read,
|
|
98 pex_win32_open_write,
|
|
99 pex_win32_exec_child,
|
|
100 pex_win32_close,
|
|
101 pex_win32_wait,
|
|
102 pex_win32_pipe,
|
|
103 pex_win32_fdopenr,
|
|
104 pex_win32_fdopenw,
|
|
105 NULL /* cleanup */
|
|
106 };
|
|
107
|
|
108 /* Return a newly initialized pex_obj structure. */
|
|
109
|
|
110 struct pex_obj *
|
|
111 pex_init (int flags, const char *pname, const char *tempbase)
|
|
112 {
|
|
113 return pex_init_common (flags, pname, tempbase, &funcs);
|
|
114 }
|
|
115
|
|
116 /* Open a file for reading. */
|
|
117
|
|
118 static int
|
|
119 pex_win32_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
|
|
120 int binary)
|
|
121 {
|
|
122 return _open (name, _O_RDONLY | (binary ? _O_BINARY : _O_TEXT));
|
|
123 }
|
|
124
|
|
125 /* Open a file for writing. */
|
|
126
|
|
127 static int
|
|
128 pex_win32_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
|
|
129 int binary)
|
|
130 {
|
|
131 /* Note that we can't use O_EXCL here because gcc may have already
|
|
132 created the temporary file via make_temp_file. */
|
|
133 return _open (name,
|
|
134 (_O_WRONLY | _O_CREAT | _O_TRUNC
|
|
135 | (binary ? _O_BINARY : _O_TEXT)),
|
|
136 _S_IREAD | _S_IWRITE);
|
|
137 }
|
|
138
|
|
139 /* Close a file. */
|
|
140
|
|
141 static int
|
|
142 pex_win32_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd)
|
|
143 {
|
|
144 return _close (fd);
|
|
145 }
|
|
146
|
|
147 #ifdef USE_MINGW_MSYS
|
|
148 static const char *mingw_keys[] = {"SOFTWARE", "Microsoft", "Windows", "CurrentVersion", "Uninstall", NULL};
|
|
149
|
|
150 /* Tack the executable on the end of a (possibly slash terminated) buffer
|
|
151 and convert everything to \. */
|
|
152 static const char *
|
|
153 tack_on_executable (char *buf, const char *executable)
|
|
154 {
|
|
155 char *p = strchr (buf, '\0');
|
|
156 if (p > buf && (p[-1] == '\\' || p[-1] == '/'))
|
|
157 p[-1] = '\0';
|
|
158 backslashify (strcat (buf, executable));
|
|
159 return buf;
|
|
160 }
|
|
161
|
|
162 /* Walk down a registry hierarchy until the end. Return the key. */
|
|
163 static HKEY
|
|
164 openkey (HKEY hStart, const char *keys[])
|
|
165 {
|
|
166 HKEY hKey, hTmp;
|
|
167 for (hKey = hStart; *keys; keys++)
|
|
168 {
|
|
169 LONG res;
|
|
170 hTmp = hKey;
|
|
171 res = RegOpenKey (hTmp, *keys, &hKey);
|
|
172
|
|
173 if (hTmp != HKEY_LOCAL_MACHINE)
|
|
174 RegCloseKey (hTmp);
|
|
175
|
|
176 if (res != ERROR_SUCCESS)
|
|
177 return NULL;
|
|
178 }
|
|
179 return hKey;
|
|
180 }
|
|
181
|
|
182 /* Return the "mingw root" as derived from the mingw uninstall information. */
|
|
183 static const char *
|
|
184 mingw_rootify (const char *executable)
|
|
185 {
|
|
186 HKEY hKey, hTmp;
|
|
187 DWORD maxlen;
|
|
188 char *namebuf, *foundbuf;
|
|
189 DWORD i;
|
|
190 LONG res;
|
|
191
|
|
192 /* Open the uninstall "directory". */
|
|
193 hKey = openkey (HKEY_LOCAL_MACHINE, mingw_keys);
|
|
194
|
|
195 /* Not found. */
|
|
196 if (!hKey)
|
|
197 return executable;
|
|
198
|
|
199 /* Need to enumerate all of the keys here looking for one the most recent
|
|
200 one for MinGW. */
|
|
201 if (RegQueryInfoKey (hKey, NULL, NULL, NULL, NULL, &maxlen, NULL, NULL,
|
|
202 NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
|
|
203 {
|
|
204 RegCloseKey (hKey);
|
|
205 return executable;
|
|
206 }
|
|
207 namebuf = XNEWVEC (char, ++maxlen);
|
|
208 foundbuf = XNEWVEC (char, maxlen);
|
|
209 foundbuf[0] = '\0';
|
|
210 if (!namebuf || !foundbuf)
|
|
211 {
|
|
212 RegCloseKey (hKey);
|
|
213 if (namebuf)
|
|
214 free (namebuf);
|
|
215 if (foundbuf)
|
|
216 free (foundbuf);
|
|
217 return executable;
|
|
218 }
|
|
219
|
|
220 /* Look through all of the keys for one that begins with Minimal GNU...
|
|
221 Try to get the latest version by doing a string compare although that
|
|
222 string never really works with version number sorting. */
|
|
223 for (i = 0; RegEnumKey (hKey, i, namebuf, maxlen) == ERROR_SUCCESS; i++)
|
|
224 {
|
|
225 int match = strcasecmp (namebuf, MINGW_NAME);
|
|
226 if (match < 0)
|
|
227 continue;
|
|
228 if (match > 0 && strncasecmp (namebuf, MINGW_NAME, MINGW_NAME_LEN) > 0)
|
|
229 continue;
|
|
230 if (strcasecmp (namebuf, foundbuf) > 0)
|
|
231 strcpy (foundbuf, namebuf);
|
|
232 }
|
|
233 free (namebuf);
|
|
234
|
|
235 /* If foundbuf is empty, we didn't find anything. Punt. */
|
|
236 if (!foundbuf[0])
|
|
237 {
|
|
238 free (foundbuf);
|
|
239 RegCloseKey (hKey);
|
|
240 return executable;
|
|
241 }
|
|
242
|
|
243 /* Open the key that we wanted */
|
|
244 res = RegOpenKey (hKey, foundbuf, &hTmp);
|
|
245 RegCloseKey (hKey);
|
|
246 free (foundbuf);
|
|
247
|
|
248 /* Don't know why this would fail, but you gotta check */
|
|
249 if (res != ERROR_SUCCESS)
|
|
250 return executable;
|
|
251
|
|
252 maxlen = 0;
|
|
253 /* Get the length of the value pointed to by InstallLocation */
|
|
254 if (RegQueryValueEx (hTmp, "InstallLocation", 0, NULL, NULL,
|
|
255 &maxlen) != ERROR_SUCCESS || maxlen == 0)
|
|
256 {
|
|
257 RegCloseKey (hTmp);
|
|
258 return executable;
|
|
259 }
|
|
260
|
|
261 /* Allocate space for the install location */
|
|
262 foundbuf = XNEWVEC (char, maxlen + strlen (executable));
|
|
263 if (!foundbuf)
|
|
264 {
|
|
265 free (foundbuf);
|
|
266 RegCloseKey (hTmp);
|
|
267 }
|
|
268
|
|
269 /* Read the install location into the buffer */
|
|
270 res = RegQueryValueEx (hTmp, "InstallLocation", 0, NULL, (LPBYTE) foundbuf,
|
|
271 &maxlen);
|
|
272 RegCloseKey (hTmp);
|
|
273 if (res != ERROR_SUCCESS)
|
|
274 {
|
|
275 free (foundbuf);
|
|
276 return executable;
|
|
277 }
|
|
278
|
|
279 /* Concatenate the install location and the executable, turn all slashes
|
|
280 to backslashes, and return that. */
|
|
281 return tack_on_executable (foundbuf, executable);
|
|
282 }
|
|
283
|
|
284 /* Read the install location of msys from it's installation file and
|
|
285 rootify the executable based on that. */
|
|
286 static const char *
|
|
287 msys_rootify (const char *executable)
|
|
288 {
|
|
289 size_t bufsize = 64;
|
|
290 size_t execlen = strlen (executable) + 1;
|
|
291 char *buf;
|
|
292 DWORD res = 0;
|
|
293 for (;;)
|
|
294 {
|
|
295 buf = XNEWVEC (char, bufsize + execlen);
|
|
296 if (!buf)
|
|
297 break;
|
|
298 res = GetPrivateProfileString ("InstallSettings", "InstallPath", NULL,
|
|
299 buf, bufsize, "msys.ini");
|
|
300 if (!res)
|
|
301 break;
|
|
302 if (strlen (buf) < bufsize)
|
|
303 break;
|
|
304 res = 0;
|
|
305 free (buf);
|
|
306 bufsize *= 2;
|
|
307 if (bufsize > 65536)
|
|
308 {
|
|
309 buf = NULL;
|
|
310 break;
|
|
311 }
|
|
312 }
|
|
313
|
|
314 if (res)
|
|
315 return tack_on_executable (buf, executable);
|
|
316
|
|
317 /* failed */
|
|
318 if (buf)
|
|
319 free (buf);
|
|
320 return executable;
|
|
321 }
|
|
322 #endif
|
|
323
|
|
324 /* Return the number of arguments in an argv array, not including the null
|
|
325 terminating argument. */
|
|
326
|
|
327 static int
|
|
328 argv_to_argc (char *const *argv)
|
|
329 {
|
|
330 char *const *i = argv;
|
|
331 while (*i)
|
|
332 i++;
|
|
333 return i - argv;
|
|
334 }
|
|
335
|
|
336 /* Return a Windows command-line from ARGV. It is the caller's
|
|
337 responsibility to free the string returned. */
|
|
338
|
|
339 static char *
|
|
340 argv_to_cmdline (char *const *argv)
|
|
341 {
|
|
342 char *cmdline;
|
|
343 char *p;
|
|
344 size_t cmdline_len;
|
|
345 int i, j, k;
|
|
346
|
|
347 cmdline_len = 0;
|
|
348 for (i = 0; argv[i]; i++)
|
|
349 {
|
|
350 /* We quote every last argument. This simplifies the problem;
|
|
351 we need only escape embedded double-quotes and immediately
|
|
352 preceeding backslash characters. A sequence of backslach characters
|
|
353 that is not follwed by a double quote character will not be
|
|
354 escaped. */
|
|
355 for (j = 0; argv[i][j]; j++)
|
|
356 {
|
|
357 if (argv[i][j] == '"')
|
|
358 {
|
|
359 /* Escape preceeding backslashes. */
|
|
360 for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
|
|
361 cmdline_len++;
|
|
362 /* Escape the qote character. */
|
|
363 cmdline_len++;
|
|
364 }
|
|
365 }
|
|
366 /* Trailing backslashes also need to be escaped because they will be
|
|
367 followed by the terminating quote. */
|
|
368 for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
|
|
369 cmdline_len++;
|
|
370 cmdline_len += j;
|
|
371 cmdline_len += 3; /* for leading and trailing quotes and space */
|
|
372 }
|
|
373 cmdline = XNEWVEC (char, cmdline_len);
|
|
374 p = cmdline;
|
|
375 for (i = 0; argv[i]; i++)
|
|
376 {
|
|
377 *p++ = '"';
|
|
378 for (j = 0; argv[i][j]; j++)
|
|
379 {
|
|
380 if (argv[i][j] == '"')
|
|
381 {
|
|
382 for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
|
|
383 *p++ = '\\';
|
|
384 *p++ = '\\';
|
|
385 }
|
|
386 *p++ = argv[i][j];
|
|
387 }
|
|
388 for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
|
|
389 *p++ = '\\';
|
|
390 *p++ = '"';
|
|
391 *p++ = ' ';
|
|
392 }
|
|
393 p[-1] = '\0';
|
|
394 return cmdline;
|
|
395 }
|
|
396
|
|
397 /* We'll try the passed filename with all the known standard
|
|
398 extensions, and then without extension. We try no extension
|
|
399 last so that we don't try to run some random extension-less
|
|
400 file that might be hanging around. We try both extension
|
|
401 and no extension so that we don't need any fancy logic
|
|
402 to determine if a file has extension. */
|
|
403 static const char *const
|
|
404 std_suffixes[] = {
|
|
405 ".com",
|
|
406 ".exe",
|
|
407 ".bat",
|
|
408 ".cmd",
|
|
409 "",
|
|
410 0
|
|
411 };
|
|
412
|
|
413 /* Returns the full path to PROGRAM. If SEARCH is true, look for
|
|
414 PROGRAM in each directory in PATH. */
|
|
415
|
|
416 static char *
|
|
417 find_executable (const char *program, BOOL search)
|
|
418 {
|
|
419 char *full_executable;
|
|
420 char *e;
|
|
421 size_t fe_len;
|
|
422 const char *path = 0;
|
|
423 const char *const *ext;
|
|
424 const char *p, *q;
|
|
425 size_t proglen = strlen (program);
|
|
426 int has_slash = (strchr (program, '/') || strchr (program, '\\'));
|
|
427 HANDLE h;
|
|
428
|
|
429 if (has_slash)
|
|
430 search = FALSE;
|
|
431
|
|
432 if (search)
|
|
433 path = getenv ("PATH");
|
|
434 if (!path)
|
|
435 path = "";
|
|
436
|
|
437 fe_len = 0;
|
|
438 for (p = path; *p; p = q)
|
|
439 {
|
|
440 q = p;
|
|
441 while (*q != ';' && *q != '\0')
|
|
442 q++;
|
|
443 if ((size_t)(q - p) > fe_len)
|
|
444 fe_len = q - p;
|
|
445 if (*q == ';')
|
|
446 q++;
|
|
447 }
|
|
448 fe_len = fe_len + 1 + proglen + 5 /* space for extension */;
|
|
449 full_executable = XNEWVEC (char, fe_len);
|
|
450
|
|
451 p = path;
|
|
452 do
|
|
453 {
|
|
454 q = p;
|
|
455 while (*q != ';' && *q != '\0')
|
|
456 q++;
|
|
457
|
|
458 e = full_executable;
|
|
459 memcpy (e, p, q - p);
|
|
460 e += (q - p);
|
|
461 if (q - p)
|
|
462 *e++ = '\\';
|
|
463 strcpy (e, program);
|
|
464
|
|
465 if (*q == ';')
|
|
466 q++;
|
|
467
|
|
468 for (e = full_executable; *e; e++)
|
|
469 if (*e == '/')
|
|
470 *e = '\\';
|
|
471
|
|
472 /* At this point, e points to the terminating NUL character for
|
|
473 full_executable. */
|
|
474 for (ext = std_suffixes; *ext; ext++)
|
|
475 {
|
|
476 /* Remove any current extension. */
|
|
477 *e = '\0';
|
|
478 /* Add the new one. */
|
|
479 strcat (full_executable, *ext);
|
|
480
|
|
481 /* Attempt to open this file. */
|
|
482 h = CreateFile (full_executable, GENERIC_READ,
|
|
483 FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
484 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
|
485 if (h != INVALID_HANDLE_VALUE)
|
|
486 goto found;
|
|
487 }
|
|
488 p = q;
|
|
489 }
|
|
490 while (*p);
|
|
491 free (full_executable);
|
|
492 return 0;
|
|
493
|
|
494 found:
|
|
495 CloseHandle (h);
|
|
496 return full_executable;
|
|
497 }
|
|
498
|
|
499 /* Low-level process creation function and helper. */
|
|
500
|
|
501 static int
|
|
502 env_compare (const void *a_ptr, const void *b_ptr)
|
|
503 {
|
|
504 const char *a;
|
|
505 const char *b;
|
|
506 unsigned char c1;
|
|
507 unsigned char c2;
|
|
508
|
|
509 a = *(const char **) a_ptr;
|
|
510 b = *(const char **) b_ptr;
|
|
511
|
|
512 /* a and b will be of the form: VAR=VALUE
|
|
513 We compare only the variable name part here using a case-insensitive
|
|
514 comparison algorithm. It might appear that in fact strcasecmp () can
|
|
515 take the place of this whole function, and indeed it could, save for
|
|
516 the fact that it would fail in cases such as comparing A1=foo and
|
|
517 A=bar (because 1 is less than = in the ASCII character set).
|
|
518 (Environment variables containing no numbers would work in such a
|
|
519 scenario.) */
|
|
520
|
|
521 do
|
|
522 {
|
|
523 c1 = (unsigned char) tolower (*a++);
|
|
524 c2 = (unsigned char) tolower (*b++);
|
|
525
|
|
526 if (c1 == '=')
|
|
527 c1 = '\0';
|
|
528
|
|
529 if (c2 == '=')
|
|
530 c2 = '\0';
|
|
531 }
|
|
532 while (c1 == c2 && c1 != '\0');
|
|
533
|
|
534 return c1 - c2;
|
|
535 }
|
|
536
|
|
537 /* Execute a Windows executable as a child process. This will fail if the
|
|
538 * target is not actually an executable, such as if it is a shell script. */
|
|
539
|
|
540 static pid_t
|
|
541 win32_spawn (const char *executable,
|
|
542 BOOL search,
|
|
543 char *const *argv,
|
|
544 char *const *env, /* array of strings of the form: VAR=VALUE */
|
|
545 DWORD dwCreationFlags,
|
|
546 LPSTARTUPINFO si,
|
|
547 LPPROCESS_INFORMATION pi)
|
|
548 {
|
|
549 char *full_executable;
|
|
550 char *cmdline;
|
|
551 char **env_copy;
|
|
552 char *env_block = NULL;
|
|
553
|
|
554 full_executable = NULL;
|
|
555 cmdline = NULL;
|
|
556
|
|
557 if (env)
|
|
558 {
|
|
559 int env_size;
|
|
560
|
|
561 /* Count the number of environment bindings supplied. */
|
|
562 for (env_size = 0; env[env_size]; env_size++)
|
|
563 continue;
|
|
564
|
|
565 /* Assemble an environment block, if required. This consists of
|
|
566 VAR=VALUE strings juxtaposed (with one null character between each
|
|
567 pair) and an additional null at the end. */
|
|
568 if (env_size > 0)
|
|
569 {
|
|
570 int var;
|
|
571 int total_size = 1; /* 1 is for the final null. */
|
|
572 char *bufptr;
|
|
573
|
|
574 /* Windows needs the members of the block to be sorted by variable
|
|
575 name. */
|
|
576 env_copy = (char **) alloca (sizeof (char *) * env_size);
|
|
577 memcpy (env_copy, env, sizeof (char *) * env_size);
|
|
578 qsort (env_copy, env_size, sizeof (char *), env_compare);
|
|
579
|
|
580 for (var = 0; var < env_size; var++)
|
|
581 total_size += strlen (env[var]) + 1;
|
|
582
|
|
583 env_block = XNEWVEC (char, total_size);
|
|
584 bufptr = env_block;
|
|
585 for (var = 0; var < env_size; var++)
|
|
586 bufptr = stpcpy (bufptr, env_copy[var]) + 1;
|
|
587
|
|
588 *bufptr = '\0';
|
|
589 }
|
|
590 }
|
|
591
|
|
592 full_executable = find_executable (executable, search);
|
|
593 if (!full_executable)
|
|
594 goto error;
|
|
595 cmdline = argv_to_cmdline (argv);
|
|
596 if (!cmdline)
|
|
597 goto error;
|
|
598
|
|
599 /* Create the child process. */
|
|
600 if (!CreateProcess (full_executable, cmdline,
|
|
601 /*lpProcessAttributes=*/NULL,
|
|
602 /*lpThreadAttributes=*/NULL,
|
|
603 /*bInheritHandles=*/TRUE,
|
|
604 dwCreationFlags,
|
|
605 (LPVOID) env_block,
|
|
606 /*lpCurrentDirectory=*/NULL,
|
|
607 si,
|
|
608 pi))
|
|
609 {
|
|
610 if (env_block)
|
|
611 free (env_block);
|
|
612
|
|
613 free (full_executable);
|
|
614
|
|
615 return (pid_t) -1;
|
|
616 }
|
|
617
|
|
618 /* Clean up. */
|
|
619 CloseHandle (pi->hThread);
|
|
620 free (full_executable);
|
|
621 if (env_block)
|
|
622 free (env_block);
|
|
623
|
|
624 return (pid_t) pi->hProcess;
|
|
625
|
|
626 error:
|
|
627 if (env_block)
|
|
628 free (env_block);
|
|
629 if (cmdline)
|
|
630 free (cmdline);
|
|
631 if (full_executable)
|
|
632 free (full_executable);
|
|
633
|
|
634 return (pid_t) -1;
|
|
635 }
|
|
636
|
|
637 /* Spawn a script. This simulates the Unix script execution mechanism.
|
|
638 This function is called as a fallback if win32_spawn fails. */
|
|
639
|
|
640 static pid_t
|
|
641 spawn_script (const char *executable, char *const *argv,
|
|
642 char* const *env,
|
|
643 DWORD dwCreationFlags,
|
|
644 LPSTARTUPINFO si,
|
|
645 LPPROCESS_INFORMATION pi)
|
|
646 {
|
|
647 pid_t pid = (pid_t) -1;
|
|
648 int save_errno = errno;
|
|
649 int fd = _open (executable, _O_RDONLY);
|
|
650
|
|
651 /* Try to open script, check header format, extract interpreter path,
|
|
652 and spawn script using that interpretter. */
|
|
653 if (fd >= 0)
|
|
654 {
|
|
655 char buf[MAX_PATH + 5];
|
|
656 int len = _read (fd, buf, sizeof (buf) - 1);
|
|
657 _close (fd);
|
|
658 if (len > 3)
|
|
659 {
|
|
660 char *eol;
|
|
661 buf[len] = '\0';
|
|
662 eol = strchr (buf, '\n');
|
|
663 if (eol && strncmp (buf, "#!", 2) == 0)
|
|
664 {
|
|
665
|
|
666 /* Header format is OK. */
|
|
667 char *executable1;
|
|
668 int new_argc;
|
|
669 const char **avhere;
|
|
670
|
|
671 /* Extract interpreter path. */
|
|
672 do
|
|
673 *eol = '\0';
|
|
674 while (*--eol == '\r' || *eol == ' ' || *eol == '\t');
|
|
675 for (executable1 = buf + 2; *executable1 == ' ' || *executable1 == '\t'; executable1++)
|
|
676 continue;
|
|
677 backslashify (executable1);
|
|
678
|
|
679 /* Duplicate argv, prepending the interpreter path. */
|
|
680 new_argc = argv_to_argc (argv) + 1;
|
|
681 avhere = XNEWVEC (const char *, new_argc + 1);
|
|
682 *avhere = executable1;
|
|
683 memcpy (avhere + 1, argv, new_argc * sizeof(*argv));
|
|
684 argv = (char *const *)avhere;
|
|
685
|
|
686 /* Spawn the child. */
|
|
687 #ifndef USE_MINGW_MSYS
|
|
688 executable = strrchr (executable1, '\\') + 1;
|
|
689 if (!executable)
|
|
690 executable = executable1;
|
|
691 pid = win32_spawn (executable, TRUE, argv, env,
|
|
692 dwCreationFlags, si, pi);
|
|
693 #else
|
|
694 if (strchr (executable1, '\\') == NULL)
|
|
695 pid = win32_spawn (executable1, TRUE, argv, env,
|
|
696 dwCreationFlags, si, pi);
|
|
697 else if (executable1[0] != '\\')
|
|
698 pid = win32_spawn (executable1, FALSE, argv, env,
|
|
699 dwCreationFlags, si, pi);
|
|
700 else
|
|
701 {
|
|
702 const char *newex = mingw_rootify (executable1);
|
|
703 *avhere = newex;
|
|
704 pid = win32_spawn (newex, FALSE, argv, env,
|
|
705 dwCreationFlags, si, pi);
|
|
706 if (executable1 != newex)
|
|
707 free ((char *) newex);
|
|
708 if ((long) pid < 0)
|
|
709 {
|
|
710 newex = msys_rootify (executable1);
|
|
711 if (newex != executable1)
|
|
712 {
|
|
713 *avhere = newex;
|
|
714 pid = win32_spawn (newex, FALSE, argv, env,
|
|
715 dwCreationFlags, si, pi);
|
|
716 free ((char *) newex);
|
|
717 }
|
|
718 }
|
|
719 }
|
|
720 #endif
|
|
721 free (avhere);
|
|
722 }
|
|
723 }
|
|
724 }
|
|
725 if ((long) pid < 0)
|
|
726 errno = save_errno;
|
|
727 return pid;
|
|
728 }
|
|
729
|
|
730 /* Execute a child. */
|
|
731
|
|
732 static pid_t
|
|
733 pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags,
|
|
734 const char *executable, char * const * argv,
|
|
735 char* const* env,
|
|
736 int in, int out, int errdes,
|
|
737 int toclose ATTRIBUTE_UNUSED,
|
|
738 const char **errmsg,
|
|
739 int *err)
|
|
740 {
|
|
741 pid_t pid;
|
|
742 HANDLE stdin_handle;
|
|
743 HANDLE stdout_handle;
|
|
744 HANDLE stderr_handle;
|
|
745 DWORD dwCreationFlags;
|
|
746 OSVERSIONINFO version_info;
|
|
747 STARTUPINFO si;
|
|
748 PROCESS_INFORMATION pi;
|
|
749
|
|
750 stdin_handle = INVALID_HANDLE_VALUE;
|
|
751 stdout_handle = INVALID_HANDLE_VALUE;
|
|
752 stderr_handle = INVALID_HANDLE_VALUE;
|
|
753
|
|
754 stdin_handle = (HANDLE) _get_osfhandle (in);
|
|
755 stdout_handle = (HANDLE) _get_osfhandle (out);
|
|
756 if (!(flags & PEX_STDERR_TO_STDOUT))
|
|
757 stderr_handle = (HANDLE) _get_osfhandle (errdes);
|
|
758 else
|
|
759 stderr_handle = stdout_handle;
|
|
760
|
|
761 /* Determine the version of Windows we are running on. */
|
|
762 version_info.dwOSVersionInfoSize = sizeof (version_info);
|
|
763 GetVersionEx (&version_info);
|
|
764 if (version_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
|
|
765 /* On Windows 95/98/ME the CREATE_NO_WINDOW flag is not
|
|
766 supported, so we cannot avoid creating a console window. */
|
|
767 dwCreationFlags = 0;
|
|
768 else
|
|
769 {
|
|
770 HANDLE conout_handle;
|
|
771
|
|
772 /* Determine whether or not we have an associated console. */
|
|
773 conout_handle = CreateFile("CONOUT$",
|
|
774 GENERIC_WRITE,
|
|
775 FILE_SHARE_WRITE,
|
|
776 /*lpSecurityAttributes=*/NULL,
|
|
777 OPEN_EXISTING,
|
|
778 FILE_ATTRIBUTE_NORMAL,
|
|
779 /*hTemplateFile=*/NULL);
|
|
780 if (conout_handle == INVALID_HANDLE_VALUE)
|
|
781 /* There is no console associated with this process. Since
|
|
782 the child is a console process, the OS would normally
|
|
783 create a new console Window for the child. Since we'll be
|
|
784 redirecting the child's standard streams, we do not need
|
|
785 the console window. */
|
|
786 dwCreationFlags = CREATE_NO_WINDOW;
|
|
787 else
|
|
788 {
|
|
789 /* There is a console associated with the process, so the OS
|
|
790 will not create a new console. And, if we use
|
|
791 CREATE_NO_WINDOW in this situation, the child will have
|
|
792 no associated console. Therefore, if the child's
|
|
793 standard streams are connected to the console, the output
|
|
794 will be discarded. */
|
|
795 CloseHandle(conout_handle);
|
|
796 dwCreationFlags = 0;
|
|
797 }
|
|
798 }
|
|
799
|
|
800 /* Since the child will be a console process, it will, by default,
|
|
801 connect standard input/output to its console. However, we want
|
|
802 the child to use the handles specifically designated above. In
|
|
803 addition, if there is no console (such as when we are running in
|
|
804 a Cygwin X window), then we must redirect the child's
|
|
805 input/output, as there is no console for the child to use. */
|
|
806 memset (&si, 0, sizeof (si));
|
|
807 si.cb = sizeof (si);
|
|
808 si.dwFlags = STARTF_USESTDHANDLES;
|
|
809 si.hStdInput = stdin_handle;
|
|
810 si.hStdOutput = stdout_handle;
|
|
811 si.hStdError = stderr_handle;
|
|
812
|
|
813 /* Create the child process. */
|
|
814 pid = win32_spawn (executable, (flags & PEX_SEARCH) != 0,
|
|
815 argv, env, dwCreationFlags, &si, &pi);
|
|
816 if (pid == (pid_t) -1)
|
|
817 pid = spawn_script (executable, argv, env, dwCreationFlags,
|
|
818 &si, &pi);
|
|
819 if (pid == (pid_t) -1)
|
|
820 {
|
|
821 *err = ENOENT;
|
|
822 *errmsg = "CreateProcess";
|
|
823 }
|
|
824
|
|
825 /* Close the standard output and standard error handles in the
|
|
826 parent. */
|
|
827 if (out != STDOUT_FILENO)
|
|
828 obj->funcs->close (obj, out);
|
|
829 if (errdes != STDERR_FILENO)
|
|
830 obj->funcs->close (obj, errdes);
|
|
831
|
|
832 return pid;
|
|
833 }
|
|
834
|
|
835 /* Wait for a child process to complete. MS CRTDLL doesn't return
|
|
836 enough information in status to decide if the child exited due to a
|
|
837 signal or not, rather it simply returns an integer with the exit
|
|
838 code of the child; eg., if the child exited with an abort() call
|
|
839 and didn't have a handler for SIGABRT, it simply returns with
|
|
840 status == 3. We fix the status code to conform to the usual WIF*
|
|
841 macros. Note that WIFSIGNALED will never be true under CRTDLL. */
|
|
842
|
|
843 static int
|
|
844 pex_win32_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid,
|
|
845 int *status, struct pex_time *time, int done ATTRIBUTE_UNUSED,
|
|
846 const char **errmsg, int *err)
|
|
847 {
|
|
848 DWORD termstat;
|
|
849 HANDLE h;
|
|
850
|
|
851 if (time != NULL)
|
|
852 memset (time, 0, sizeof *time);
|
|
853
|
|
854 h = (HANDLE) pid;
|
|
855
|
|
856 /* FIXME: If done is non-zero, we should probably try to kill the
|
|
857 process. */
|
|
858 if (WaitForSingleObject (h, INFINITE) != WAIT_OBJECT_0)
|
|
859 {
|
|
860 CloseHandle (h);
|
|
861 *err = ECHILD;
|
|
862 *errmsg = "WaitForSingleObject";
|
|
863 return -1;
|
|
864 }
|
|
865
|
|
866 GetExitCodeProcess (h, &termstat);
|
|
867 CloseHandle (h);
|
|
868
|
|
869 /* A value of 3 indicates that the child caught a signal, but not
|
|
870 which one. Since only SIGABRT, SIGFPE and SIGINT do anything, we
|
|
871 report SIGABRT. */
|
|
872 if (termstat == 3)
|
|
873 *status = SIGABRT;
|
|
874 else
|
|
875 *status = (termstat & 0xff) << 8;
|
|
876
|
|
877 return 0;
|
|
878 }
|
|
879
|
|
880 /* Create a pipe. */
|
|
881
|
|
882 static int
|
|
883 pex_win32_pipe (struct pex_obj *obj ATTRIBUTE_UNUSED, int *p,
|
|
884 int binary)
|
|
885 {
|
|
886 return _pipe (p, 256, binary ? _O_BINARY : _O_TEXT);
|
|
887 }
|
|
888
|
|
889 /* Get a FILE pointer to read from a file descriptor. */
|
|
890
|
|
891 static FILE *
|
|
892 pex_win32_fdopenr (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
|
|
893 int binary)
|
|
894 {
|
|
895 return fdopen (fd, binary ? "rb" : "r");
|
|
896 }
|
|
897
|
|
898 static FILE *
|
|
899 pex_win32_fdopenw (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
|
|
900 int binary)
|
|
901 {
|
|
902 HANDLE h = (HANDLE) _get_osfhandle (fd);
|
|
903 if (h == INVALID_HANDLE_VALUE)
|
|
904 return NULL;
|
|
905 if (! SetHandleInformation (h, HANDLE_FLAG_INHERIT, 0))
|
|
906 return NULL;
|
|
907 return fdopen (fd, binary ? "wb" : "w");
|
|
908 }
|
|
909
|
|
910 #ifdef MAIN
|
|
911 #include <stdio.h>
|
|
912
|
|
913 int
|
|
914 main (int argc ATTRIBUTE_UNUSED, char **argv)
|
|
915 {
|
|
916 char const *errmsg;
|
|
917 int err;
|
|
918 argv++;
|
|
919 printf ("%ld\n", (long) pex_win32_exec_child (NULL, PEX_SEARCH, argv[0], argv, NULL, 0, 0, 1, 2, &errmsg, &err));
|
|
920 exit (0);
|
|
921 }
|
|
922 #endif
|