1 | /* Utilities to execute a program in a subprocess (possibly linked by pipes |
---|
2 | with other subprocesses), and wait for it. Generic Unix version |
---|
3 | (also used for UWIN and VMS). |
---|
4 | Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2009, |
---|
5 | 2010 Free Software Foundation, Inc. |
---|
6 | |
---|
7 | This file is part of the libiberty library. |
---|
8 | Libiberty is free software; you can redistribute it and/or |
---|
9 | modify it under the terms of the GNU Library General Public |
---|
10 | License as published by the Free Software Foundation; either |
---|
11 | version 2 of the License, or (at your option) any later version. |
---|
12 | |
---|
13 | Libiberty is distributed in the hope that it will be useful, |
---|
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
16 | Library General Public License for more details. |
---|
17 | |
---|
18 | You should have received a copy of the GNU Library General Public |
---|
19 | License along with libiberty; see the file COPYING.LIB. If not, |
---|
20 | write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, |
---|
21 | Boston, MA 02110-1301, USA. */ |
---|
22 | |
---|
23 | #include "config.h" |
---|
24 | #include "libiberty.h" |
---|
25 | #include "pex-common.h" |
---|
26 | |
---|
27 | #include <stdio.h> |
---|
28 | #include <signal.h> |
---|
29 | #include <errno.h> |
---|
30 | #ifdef NEED_DECLARATION_ERRNO |
---|
31 | extern int errno; |
---|
32 | #endif |
---|
33 | #ifdef HAVE_STDLIB_H |
---|
34 | #include <stdlib.h> |
---|
35 | #endif |
---|
36 | #ifdef HAVE_STRING_H |
---|
37 | #include <string.h> |
---|
38 | #endif |
---|
39 | #ifdef HAVE_UNISTD_H |
---|
40 | #include <unistd.h> |
---|
41 | #endif |
---|
42 | |
---|
43 | #include <sys/types.h> |
---|
44 | |
---|
45 | #ifdef HAVE_FCNTL_H |
---|
46 | #include <fcntl.h> |
---|
47 | #endif |
---|
48 | #ifdef HAVE_SYS_WAIT_H |
---|
49 | #include <sys/wait.h> |
---|
50 | #endif |
---|
51 | #ifdef HAVE_GETRUSAGE |
---|
52 | #include <sys/time.h> |
---|
53 | #include <sys/resource.h> |
---|
54 | #endif |
---|
55 | #ifdef HAVE_SYS_STAT_H |
---|
56 | #include <sys/stat.h> |
---|
57 | #endif |
---|
58 | #ifdef HAVE_PROCESS_H |
---|
59 | #include <process.h> |
---|
60 | #endif |
---|
61 | |
---|
62 | #ifdef vfork /* Autoconf may define this to fork for us. */ |
---|
63 | # define VFORK_STRING "fork" |
---|
64 | #else |
---|
65 | # define VFORK_STRING "vfork" |
---|
66 | #endif |
---|
67 | #ifdef HAVE_VFORK_H |
---|
68 | #include <vfork.h> |
---|
69 | #endif |
---|
70 | #if defined(VMS) && defined (__LONG_POINTERS) |
---|
71 | #ifndef __CHAR_PTR32 |
---|
72 | typedef char * __char_ptr32 |
---|
73 | __attribute__ ((mode (SI))); |
---|
74 | #endif |
---|
75 | |
---|
76 | typedef __char_ptr32 *__char_ptr_char_ptr32 |
---|
77 | __attribute__ ((mode (SI))); |
---|
78 | |
---|
79 | /* Return a 32 bit pointer to an array of 32 bit pointers |
---|
80 | given a 64 bit pointer to an array of 64 bit pointers. */ |
---|
81 | |
---|
82 | static __char_ptr_char_ptr32 |
---|
83 | to_ptr32 (char **ptr64) |
---|
84 | { |
---|
85 | int argc; |
---|
86 | __char_ptr_char_ptr32 short_argv; |
---|
87 | |
---|
88 | for (argc=0; ptr64[argc]; argc++); |
---|
89 | |
---|
90 | /* Reallocate argv with 32 bit pointers. */ |
---|
91 | short_argv = (__char_ptr_char_ptr32) decc$malloc |
---|
92 | (sizeof (__char_ptr32) * (argc + 1)); |
---|
93 | |
---|
94 | for (argc=0; ptr64[argc]; argc++) |
---|
95 | short_argv[argc] = (__char_ptr32) decc$strdup (ptr64[argc]); |
---|
96 | |
---|
97 | short_argv[argc] = (__char_ptr32) 0; |
---|
98 | return short_argv; |
---|
99 | |
---|
100 | } |
---|
101 | #else |
---|
102 | #define to_ptr32(argv) argv |
---|
103 | #endif |
---|
104 | |
---|
105 | /* File mode to use for private and world-readable files. */ |
---|
106 | |
---|
107 | #if defined (S_IRUSR) && defined (S_IWUSR) && defined (S_IRGRP) && defined (S_IWGRP) && defined (S_IROTH) && defined (S_IWOTH) |
---|
108 | #define PUBLIC_MODE \ |
---|
109 | (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) |
---|
110 | #else |
---|
111 | #define PUBLIC_MODE 0666 |
---|
112 | #endif |
---|
113 | |
---|
114 | /* Get the exit status of a particular process, and optionally get the |
---|
115 | time that it took. This is simple if we have wait4, slightly |
---|
116 | harder if we have waitpid, and is a pain if we only have wait. */ |
---|
117 | |
---|
118 | static pid_t pex_wait (struct pex_obj *, pid_t, int *, struct pex_time *); |
---|
119 | |
---|
120 | #ifdef HAVE_WAIT4 |
---|
121 | |
---|
122 | static pid_t |
---|
123 | pex_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid, int *status, |
---|
124 | struct pex_time *time) |
---|
125 | { |
---|
126 | pid_t ret; |
---|
127 | struct rusage r; |
---|
128 | |
---|
129 | #ifdef HAVE_WAITPID |
---|
130 | if (time == NULL) |
---|
131 | return waitpid (pid, status, 0); |
---|
132 | #endif |
---|
133 | |
---|
134 | ret = wait4 (pid, status, 0, &r); |
---|
135 | |
---|
136 | if (time != NULL) |
---|
137 | { |
---|
138 | time->user_seconds = r.ru_utime.tv_sec; |
---|
139 | time->user_microseconds= r.ru_utime.tv_usec; |
---|
140 | time->system_seconds = r.ru_stime.tv_sec; |
---|
141 | time->system_microseconds= r.ru_stime.tv_usec; |
---|
142 | } |
---|
143 | |
---|
144 | return ret; |
---|
145 | } |
---|
146 | |
---|
147 | #else /* ! defined (HAVE_WAIT4) */ |
---|
148 | |
---|
149 | #ifdef HAVE_WAITPID |
---|
150 | |
---|
151 | #ifndef HAVE_GETRUSAGE |
---|
152 | |
---|
153 | static pid_t |
---|
154 | pex_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid, int *status, |
---|
155 | struct pex_time *time) |
---|
156 | { |
---|
157 | if (time != NULL) |
---|
158 | memset (time, 0, sizeof (struct pex_time)); |
---|
159 | return waitpid (pid, status, 0); |
---|
160 | } |
---|
161 | |
---|
162 | #else /* defined (HAVE_GETRUSAGE) */ |
---|
163 | |
---|
164 | static pid_t |
---|
165 | pex_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid, int *status, |
---|
166 | struct pex_time *time) |
---|
167 | { |
---|
168 | struct rusage r1, r2; |
---|
169 | pid_t ret; |
---|
170 | |
---|
171 | if (time == NULL) |
---|
172 | return waitpid (pid, status, 0); |
---|
173 | |
---|
174 | getrusage (RUSAGE_CHILDREN, &r1); |
---|
175 | |
---|
176 | ret = waitpid (pid, status, 0); |
---|
177 | if (ret < 0) |
---|
178 | return ret; |
---|
179 | |
---|
180 | getrusage (RUSAGE_CHILDREN, &r2); |
---|
181 | |
---|
182 | time->user_seconds = r2.ru_utime.tv_sec - r1.ru_utime.tv_sec; |
---|
183 | time->user_microseconds = r2.ru_utime.tv_usec - r1.ru_utime.tv_usec; |
---|
184 | if (r2.ru_utime.tv_usec < r1.ru_utime.tv_usec) |
---|
185 | { |
---|
186 | --time->user_seconds; |
---|
187 | time->user_microseconds += 1000000; |
---|
188 | } |
---|
189 | |
---|
190 | time->system_seconds = r2.ru_stime.tv_sec - r1.ru_stime.tv_sec; |
---|
191 | time->system_microseconds = r2.ru_stime.tv_usec - r1.ru_stime.tv_usec; |
---|
192 | if (r2.ru_stime.tv_usec < r1.ru_stime.tv_usec) |
---|
193 | { |
---|
194 | --time->system_seconds; |
---|
195 | time->system_microseconds += 1000000; |
---|
196 | } |
---|
197 | |
---|
198 | return ret; |
---|
199 | } |
---|
200 | |
---|
201 | #endif /* defined (HAVE_GETRUSAGE) */ |
---|
202 | |
---|
203 | #else /* ! defined (HAVE_WAITPID) */ |
---|
204 | |
---|
205 | struct status_list |
---|
206 | { |
---|
207 | struct status_list *next; |
---|
208 | pid_t pid; |
---|
209 | int status; |
---|
210 | struct pex_time time; |
---|
211 | }; |
---|
212 | |
---|
213 | static pid_t |
---|
214 | pex_wait (struct pex_obj *obj, pid_t pid, int *status, struct pex_time *time) |
---|
215 | { |
---|
216 | struct status_list **pp; |
---|
217 | |
---|
218 | for (pp = (struct status_list **) &obj->sysdep; |
---|
219 | *pp != NULL; |
---|
220 | pp = &(*pp)->next) |
---|
221 | { |
---|
222 | if ((*pp)->pid == pid) |
---|
223 | { |
---|
224 | struct status_list *p; |
---|
225 | |
---|
226 | p = *pp; |
---|
227 | *status = p->status; |
---|
228 | if (time != NULL) |
---|
229 | *time = p->time; |
---|
230 | *pp = p->next; |
---|
231 | free (p); |
---|
232 | return pid; |
---|
233 | } |
---|
234 | } |
---|
235 | |
---|
236 | while (1) |
---|
237 | { |
---|
238 | pid_t cpid; |
---|
239 | struct status_list *psl; |
---|
240 | struct pex_time pt; |
---|
241 | #ifdef HAVE_GETRUSAGE |
---|
242 | struct rusage r1, r2; |
---|
243 | #endif |
---|
244 | |
---|
245 | if (time != NULL) |
---|
246 | { |
---|
247 | #ifdef HAVE_GETRUSAGE |
---|
248 | getrusage (RUSAGE_CHILDREN, &r1); |
---|
249 | #else |
---|
250 | memset (&pt, 0, sizeof (struct pex_time)); |
---|
251 | #endif |
---|
252 | } |
---|
253 | |
---|
254 | cpid = wait (status); |
---|
255 | |
---|
256 | #ifdef HAVE_GETRUSAGE |
---|
257 | if (time != NULL && cpid >= 0) |
---|
258 | { |
---|
259 | getrusage (RUSAGE_CHILDREN, &r2); |
---|
260 | |
---|
261 | pt.user_seconds = r2.ru_utime.tv_sec - r1.ru_utime.tv_sec; |
---|
262 | pt.user_microseconds = r2.ru_utime.tv_usec - r1.ru_utime.tv_usec; |
---|
263 | if (pt.user_microseconds < 0) |
---|
264 | { |
---|
265 | --pt.user_seconds; |
---|
266 | pt.user_microseconds += 1000000; |
---|
267 | } |
---|
268 | |
---|
269 | pt.system_seconds = r2.ru_stime.tv_sec - r1.ru_stime.tv_sec; |
---|
270 | pt.system_microseconds = r2.ru_stime.tv_usec - r1.ru_stime.tv_usec; |
---|
271 | if (pt.system_microseconds < 0) |
---|
272 | { |
---|
273 | --pt.system_seconds; |
---|
274 | pt.system_microseconds += 1000000; |
---|
275 | } |
---|
276 | } |
---|
277 | #endif |
---|
278 | |
---|
279 | if (cpid < 0 || cpid == pid) |
---|
280 | { |
---|
281 | if (time != NULL) |
---|
282 | *time = pt; |
---|
283 | return cpid; |
---|
284 | } |
---|
285 | |
---|
286 | psl = XNEW (struct status_list); |
---|
287 | psl->pid = cpid; |
---|
288 | psl->status = *status; |
---|
289 | if (time != NULL) |
---|
290 | psl->time = pt; |
---|
291 | psl->next = (struct status_list *) obj->sysdep; |
---|
292 | obj->sysdep = (void *) psl; |
---|
293 | } |
---|
294 | } |
---|
295 | |
---|
296 | #endif /* ! defined (HAVE_WAITPID) */ |
---|
297 | #endif /* ! defined (HAVE_WAIT4) */ |
---|
298 | |
---|
299 | static void pex_child_error (struct pex_obj *, const char *, const char *, int) |
---|
300 | ATTRIBUTE_NORETURN; |
---|
301 | static int pex_unix_open_read (struct pex_obj *, const char *, int); |
---|
302 | static int pex_unix_open_write (struct pex_obj *, const char *, int); |
---|
303 | static pid_t pex_unix_exec_child (struct pex_obj *, int, const char *, |
---|
304 | char * const *, char * const *, |
---|
305 | int, int, int, int, |
---|
306 | const char **, int *); |
---|
307 | static int pex_unix_close (struct pex_obj *, int); |
---|
308 | static int pex_unix_wait (struct pex_obj *, pid_t, int *, struct pex_time *, |
---|
309 | int, const char **, int *); |
---|
310 | static int pex_unix_pipe (struct pex_obj *, int *, int); |
---|
311 | static FILE *pex_unix_fdopenr (struct pex_obj *, int, int); |
---|
312 | static FILE *pex_unix_fdopenw (struct pex_obj *, int, int); |
---|
313 | static void pex_unix_cleanup (struct pex_obj *); |
---|
314 | |
---|
315 | /* The list of functions we pass to the common routines. */ |
---|
316 | |
---|
317 | const struct pex_funcs funcs = |
---|
318 | { |
---|
319 | pex_unix_open_read, |
---|
320 | pex_unix_open_write, |
---|
321 | pex_unix_exec_child, |
---|
322 | pex_unix_close, |
---|
323 | pex_unix_wait, |
---|
324 | pex_unix_pipe, |
---|
325 | pex_unix_fdopenr, |
---|
326 | pex_unix_fdopenw, |
---|
327 | pex_unix_cleanup |
---|
328 | }; |
---|
329 | |
---|
330 | /* Return a newly initialized pex_obj structure. */ |
---|
331 | |
---|
332 | struct pex_obj * |
---|
333 | pex_init (int flags, const char *pname, const char *tempbase) |
---|
334 | { |
---|
335 | return pex_init_common (flags, pname, tempbase, &funcs); |
---|
336 | } |
---|
337 | |
---|
338 | /* Open a file for reading. */ |
---|
339 | |
---|
340 | static int |
---|
341 | pex_unix_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, |
---|
342 | int binary ATTRIBUTE_UNUSED) |
---|
343 | { |
---|
344 | return open (name, O_RDONLY); |
---|
345 | } |
---|
346 | |
---|
347 | /* Open a file for writing. */ |
---|
348 | |
---|
349 | static int |
---|
350 | pex_unix_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, |
---|
351 | int binary ATTRIBUTE_UNUSED) |
---|
352 | { |
---|
353 | /* Note that we can't use O_EXCL here because gcc may have already |
---|
354 | created the temporary file via make_temp_file. */ |
---|
355 | return open (name, O_WRONLY | O_CREAT | O_TRUNC, PUBLIC_MODE); |
---|
356 | } |
---|
357 | |
---|
358 | /* Close a file. */ |
---|
359 | |
---|
360 | static int |
---|
361 | pex_unix_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd) |
---|
362 | { |
---|
363 | return close (fd); |
---|
364 | } |
---|
365 | |
---|
366 | /* Report an error from a child process. We don't use stdio routines, |
---|
367 | because we might be here due to a vfork call. */ |
---|
368 | |
---|
369 | static void |
---|
370 | pex_child_error (struct pex_obj *obj, const char *executable, |
---|
371 | const char *errmsg, int err) |
---|
372 | { |
---|
373 | int retval = 0; |
---|
374 | #define writeerr(s) retval |= (write (STDERR_FILE_NO, s, strlen (s)) < 0) |
---|
375 | writeerr (obj->pname); |
---|
376 | writeerr (": error trying to exec '"); |
---|
377 | writeerr (executable); |
---|
378 | writeerr ("': "); |
---|
379 | writeerr (errmsg); |
---|
380 | writeerr (": "); |
---|
381 | writeerr (xstrerror (err)); |
---|
382 | writeerr ("\n"); |
---|
383 | #undef writeerr |
---|
384 | /* Exit with -2 if the error output failed, too. */ |
---|
385 | _exit (retval == 0 ? -1 : -2); |
---|
386 | } |
---|
387 | |
---|
388 | /* Execute a child. */ |
---|
389 | |
---|
390 | extern char **environ; |
---|
391 | |
---|
392 | #if defined(HAVE_SPAWNVE) && defined(HAVE_SPAWNVPE) |
---|
393 | /* Implementation of pex->exec_child using the Cygwin spawn operation. */ |
---|
394 | |
---|
395 | /* Subroutine of pex_unix_exec_child. Move OLD_FD to a new file descriptor |
---|
396 | to be stored in *PNEW_FD, save the flags in *PFLAGS, and arrange for the |
---|
397 | saved copy to be close-on-exec. Move CHILD_FD into OLD_FD. If CHILD_FD |
---|
398 | is -1, OLD_FD is to be closed. Return -1 on error. */ |
---|
399 | |
---|
400 | static int |
---|
401 | save_and_install_fd(int *pnew_fd, int *pflags, int old_fd, int child_fd) |
---|
402 | { |
---|
403 | int new_fd, flags; |
---|
404 | |
---|
405 | flags = fcntl (old_fd, F_GETFD); |
---|
406 | |
---|
407 | /* If we could not retrieve the flags, then OLD_FD was not open. */ |
---|
408 | if (flags < 0) |
---|
409 | { |
---|
410 | new_fd = -1, flags = 0; |
---|
411 | if (child_fd >= 0 && dup2 (child_fd, old_fd) < 0) |
---|
412 | return -1; |
---|
413 | } |
---|
414 | /* If we wish to close OLD_FD, just mark it CLOEXEC. */ |
---|
415 | else if (child_fd == -1) |
---|
416 | { |
---|
417 | new_fd = old_fd; |
---|
418 | if ((flags & FD_CLOEXEC) == 0 && fcntl (old_fd, F_SETFD, FD_CLOEXEC) < 0) |
---|
419 | return -1; |
---|
420 | } |
---|
421 | /* Otherwise we need to save a copy of OLD_FD before installing CHILD_FD. */ |
---|
422 | else |
---|
423 | { |
---|
424 | #ifdef F_DUPFD_CLOEXEC |
---|
425 | new_fd = fcntl (old_fd, F_DUPFD_CLOEXEC, 3); |
---|
426 | if (new_fd < 0) |
---|
427 | return -1; |
---|
428 | #else |
---|
429 | /* Prefer F_DUPFD over dup in order to avoid getting a new fd |
---|
430 | in the range 0-2, right where a new stderr fd might get put. */ |
---|
431 | new_fd = fcntl (old_fd, F_DUPFD, 3); |
---|
432 | if (new_fd < 0) |
---|
433 | return -1; |
---|
434 | if (fcntl (new_fd, F_SETFD, FD_CLOEXEC) < 0) |
---|
435 | return -1; |
---|
436 | #endif |
---|
437 | if (dup2 (child_fd, old_fd) < 0) |
---|
438 | return -1; |
---|
439 | } |
---|
440 | |
---|
441 | *pflags = flags; |
---|
442 | if (pnew_fd) |
---|
443 | *pnew_fd = new_fd; |
---|
444 | else if (new_fd != old_fd) |
---|
445 | abort (); |
---|
446 | |
---|
447 | return 0; |
---|
448 | } |
---|
449 | |
---|
450 | /* Subroutine of pex_unix_exec_child. Move SAVE_FD back to OLD_FD |
---|
451 | restoring FLAGS. If SAVE_FD < 0, OLD_FD is to be closed. */ |
---|
452 | |
---|
453 | static int |
---|
454 | restore_fd(int old_fd, int save_fd, int flags) |
---|
455 | { |
---|
456 | /* For SAVE_FD < 0, all we have to do is restore the |
---|
457 | "closed-ness" of the original. */ |
---|
458 | if (save_fd < 0) |
---|
459 | return close (old_fd); |
---|
460 | |
---|
461 | /* For SAVE_FD == OLD_FD, all we have to do is restore the |
---|
462 | original setting of the CLOEXEC flag. */ |
---|
463 | if (save_fd == old_fd) |
---|
464 | { |
---|
465 | if (flags & FD_CLOEXEC) |
---|
466 | return 0; |
---|
467 | return fcntl (old_fd, F_SETFD, flags); |
---|
468 | } |
---|
469 | |
---|
470 | /* Otherwise we have to move the descriptor back, restore the flags, |
---|
471 | and close the saved copy. */ |
---|
472 | #ifdef HAVE_DUP3 |
---|
473 | if (flags == FD_CLOEXEC) |
---|
474 | { |
---|
475 | if (dup3 (save_fd, old_fd, O_CLOEXEC) < 0) |
---|
476 | return -1; |
---|
477 | } |
---|
478 | else |
---|
479 | #endif |
---|
480 | { |
---|
481 | if (dup2 (save_fd, old_fd) < 0) |
---|
482 | return -1; |
---|
483 | if (flags != 0 && fcntl (old_fd, F_SETFD, flags) < 0) |
---|
484 | return -1; |
---|
485 | } |
---|
486 | return close (save_fd); |
---|
487 | } |
---|
488 | |
---|
489 | static pid_t |
---|
490 | pex_unix_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, |
---|
491 | int flags, const char *executable, |
---|
492 | char * const * argv, char * const * env, |
---|
493 | int in, int out, int errdes, int toclose, |
---|
494 | const char **errmsg, int *err) |
---|
495 | { |
---|
496 | int fl_in = 0, fl_out = 0, fl_err = 0, fl_tc = 0; |
---|
497 | int save_in = -1, save_out = -1, save_err = -1; |
---|
498 | int max, retries; |
---|
499 | pid_t pid; |
---|
500 | |
---|
501 | if (flags & PEX_STDERR_TO_STDOUT) |
---|
502 | errdes = out; |
---|
503 | |
---|
504 | /* We need the three standard file descriptors to be set up as for |
---|
505 | the child before we perform the spawn. The file descriptors for |
---|
506 | the parent need to be moved and marked for close-on-exec. */ |
---|
507 | if (in != STDIN_FILE_NO |
---|
508 | && save_and_install_fd (&save_in, &fl_in, STDIN_FILE_NO, in) < 0) |
---|
509 | goto error_dup2; |
---|
510 | if (out != STDOUT_FILE_NO |
---|
511 | && save_and_install_fd (&save_out, &fl_out, STDOUT_FILE_NO, out) < 0) |
---|
512 | goto error_dup2; |
---|
513 | if (errdes != STDERR_FILE_NO |
---|
514 | && save_and_install_fd (&save_err, &fl_err, STDERR_FILE_NO, errdes) < 0) |
---|
515 | goto error_dup2; |
---|
516 | if (toclose >= 0 |
---|
517 | && save_and_install_fd (NULL, &fl_tc, toclose, -1) < 0) |
---|
518 | goto error_dup2; |
---|
519 | |
---|
520 | /* Now that we've moved the file descriptors for the child into place, |
---|
521 | close the originals. Be careful not to close any of the standard |
---|
522 | file descriptors that we just set up. */ |
---|
523 | max = -1; |
---|
524 | if (errdes >= 0) |
---|
525 | max = STDERR_FILE_NO; |
---|
526 | else if (out >= 0) |
---|
527 | max = STDOUT_FILE_NO; |
---|
528 | else if (in >= 0) |
---|
529 | max = STDIN_FILE_NO; |
---|
530 | if (in > max) |
---|
531 | close (in); |
---|
532 | if (out > max) |
---|
533 | close (out); |
---|
534 | if (errdes > max && errdes != out) |
---|
535 | close (errdes); |
---|
536 | |
---|
537 | /* If we were not given an environment, use the global environment. */ |
---|
538 | if (env == NULL) |
---|
539 | env = environ; |
---|
540 | |
---|
541 | /* Launch the program. If we get EAGAIN (normally out of pid's), try |
---|
542 | again a few times with increasing backoff times. */ |
---|
543 | retries = 0; |
---|
544 | while (1) |
---|
545 | { |
---|
546 | typedef const char * const *cc_cp; |
---|
547 | |
---|
548 | if (flags & PEX_SEARCH) |
---|
549 | pid = spawnvpe (_P_NOWAITO, executable, (cc_cp)argv, (cc_cp)env); |
---|
550 | else |
---|
551 | pid = spawnve (_P_NOWAITO, executable, (cc_cp)argv, (cc_cp)env); |
---|
552 | |
---|
553 | if (pid > 0) |
---|
554 | break; |
---|
555 | |
---|
556 | *err = errno; |
---|
557 | *errmsg = "spawn"; |
---|
558 | if (errno != EAGAIN || ++retries == 4) |
---|
559 | return (pid_t) -1; |
---|
560 | sleep (1 << retries); |
---|
561 | } |
---|
562 | |
---|
563 | /* Success. Restore the parent's file descriptors that we saved above. */ |
---|
564 | if (toclose >= 0 |
---|
565 | && restore_fd (toclose, toclose, fl_tc) < 0) |
---|
566 | goto error_dup2; |
---|
567 | if (in != STDIN_FILE_NO |
---|
568 | && restore_fd (STDIN_FILE_NO, save_in, fl_in) < 0) |
---|
569 | goto error_dup2; |
---|
570 | if (out != STDOUT_FILE_NO |
---|
571 | && restore_fd (STDOUT_FILE_NO, save_out, fl_out) < 0) |
---|
572 | goto error_dup2; |
---|
573 | if (errdes != STDERR_FILE_NO |
---|
574 | && restore_fd (STDERR_FILE_NO, save_err, fl_err) < 0) |
---|
575 | goto error_dup2; |
---|
576 | |
---|
577 | return pid; |
---|
578 | |
---|
579 | error_dup2: |
---|
580 | *err = errno; |
---|
581 | *errmsg = "dup2"; |
---|
582 | return (pid_t) -1; |
---|
583 | } |
---|
584 | |
---|
585 | #else |
---|
586 | /* Implementation of pex->exec_child using standard vfork + exec. */ |
---|
587 | |
---|
588 | static pid_t |
---|
589 | pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable, |
---|
590 | char * const * argv, char * const * env, |
---|
591 | int in, int out, int errdes, |
---|
592 | int toclose, const char **errmsg, int *err) |
---|
593 | { |
---|
594 | pid_t pid; |
---|
595 | |
---|
596 | /* We declare these to be volatile to avoid warnings from gcc about |
---|
597 | them being clobbered by vfork. */ |
---|
598 | volatile int sleep_interval; |
---|
599 | volatile int retries; |
---|
600 | |
---|
601 | /* We vfork and then set environ in the child before calling execvp. |
---|
602 | This clobbers the parent's environ so we need to restore it. |
---|
603 | It would be nice to use one of the exec* functions that takes an |
---|
604 | environment as a parameter, but that may have portability issues. */ |
---|
605 | char **save_environ = environ; |
---|
606 | |
---|
607 | sleep_interval = 1; |
---|
608 | pid = -1; |
---|
609 | for (retries = 0; retries < 4; ++retries) |
---|
610 | { |
---|
611 | pid = vfork (); |
---|
612 | if (pid >= 0) |
---|
613 | break; |
---|
614 | sleep (sleep_interval); |
---|
615 | sleep_interval *= 2; |
---|
616 | } |
---|
617 | |
---|
618 | switch (pid) |
---|
619 | { |
---|
620 | case -1: |
---|
621 | *err = errno; |
---|
622 | *errmsg = VFORK_STRING; |
---|
623 | return (pid_t) -1; |
---|
624 | |
---|
625 | case 0: |
---|
626 | /* Child process. */ |
---|
627 | if (in != STDIN_FILE_NO) |
---|
628 | { |
---|
629 | if (dup2 (in, STDIN_FILE_NO) < 0) |
---|
630 | pex_child_error (obj, executable, "dup2", errno); |
---|
631 | if (close (in) < 0) |
---|
632 | pex_child_error (obj, executable, "close", errno); |
---|
633 | } |
---|
634 | if (out != STDOUT_FILE_NO) |
---|
635 | { |
---|
636 | if (dup2 (out, STDOUT_FILE_NO) < 0) |
---|
637 | pex_child_error (obj, executable, "dup2", errno); |
---|
638 | if (close (out) < 0) |
---|
639 | pex_child_error (obj, executable, "close", errno); |
---|
640 | } |
---|
641 | if (errdes != STDERR_FILE_NO) |
---|
642 | { |
---|
643 | if (dup2 (errdes, STDERR_FILE_NO) < 0) |
---|
644 | pex_child_error (obj, executable, "dup2", errno); |
---|
645 | if (close (errdes) < 0) |
---|
646 | pex_child_error (obj, executable, "close", errno); |
---|
647 | } |
---|
648 | if (toclose >= 0) |
---|
649 | { |
---|
650 | if (close (toclose) < 0) |
---|
651 | pex_child_error (obj, executable, "close", errno); |
---|
652 | } |
---|
653 | if ((flags & PEX_STDERR_TO_STDOUT) != 0) |
---|
654 | { |
---|
655 | if (dup2 (STDOUT_FILE_NO, STDERR_FILE_NO) < 0) |
---|
656 | pex_child_error (obj, executable, "dup2", errno); |
---|
657 | } |
---|
658 | |
---|
659 | if (env) |
---|
660 | { |
---|
661 | /* NOTE: In a standard vfork implementation this clobbers the |
---|
662 | parent's copy of environ "too" (in reality there's only one copy). |
---|
663 | This is ok as we restore it below. */ |
---|
664 | environ = (char**) env; |
---|
665 | } |
---|
666 | |
---|
667 | if ((flags & PEX_SEARCH) != 0) |
---|
668 | { |
---|
669 | execvp (executable, to_ptr32 (argv)); |
---|
670 | pex_child_error (obj, executable, "execvp", errno); |
---|
671 | } |
---|
672 | else |
---|
673 | { |
---|
674 | execv (executable, to_ptr32 (argv)); |
---|
675 | pex_child_error (obj, executable, "execv", errno); |
---|
676 | } |
---|
677 | |
---|
678 | /* NOTREACHED */ |
---|
679 | return (pid_t) -1; |
---|
680 | |
---|
681 | default: |
---|
682 | /* Parent process. */ |
---|
683 | |
---|
684 | /* Restore environ. |
---|
685 | Note that the parent either doesn't run until the child execs/exits |
---|
686 | (standard vfork behaviour), or if it does run then vfork is behaving |
---|
687 | more like fork. In either case we needn't worry about clobbering |
---|
688 | the child's copy of environ. */ |
---|
689 | environ = save_environ; |
---|
690 | |
---|
691 | if (in != STDIN_FILE_NO) |
---|
692 | { |
---|
693 | if (close (in) < 0) |
---|
694 | { |
---|
695 | *err = errno; |
---|
696 | *errmsg = "close"; |
---|
697 | return (pid_t) -1; |
---|
698 | } |
---|
699 | } |
---|
700 | if (out != STDOUT_FILE_NO) |
---|
701 | { |
---|
702 | if (close (out) < 0) |
---|
703 | { |
---|
704 | *err = errno; |
---|
705 | *errmsg = "close"; |
---|
706 | return (pid_t) -1; |
---|
707 | } |
---|
708 | } |
---|
709 | if (errdes != STDERR_FILE_NO) |
---|
710 | { |
---|
711 | if (close (errdes) < 0) |
---|
712 | { |
---|
713 | *err = errno; |
---|
714 | *errmsg = "close"; |
---|
715 | return (pid_t) -1; |
---|
716 | } |
---|
717 | } |
---|
718 | |
---|
719 | return pid; |
---|
720 | } |
---|
721 | } |
---|
722 | #endif /* SPAWN */ |
---|
723 | |
---|
724 | /* Wait for a child process to complete. */ |
---|
725 | |
---|
726 | static int |
---|
727 | pex_unix_wait (struct pex_obj *obj, pid_t pid, int *status, |
---|
728 | struct pex_time *time, int done, const char **errmsg, |
---|
729 | int *err) |
---|
730 | { |
---|
731 | /* If we are cleaning up when the caller didn't retrieve process |
---|
732 | status for some reason, encourage the process to go away. */ |
---|
733 | if (done) |
---|
734 | kill (pid, SIGTERM); |
---|
735 | |
---|
736 | if (pex_wait (obj, pid, status, time) < 0) |
---|
737 | { |
---|
738 | *err = errno; |
---|
739 | *errmsg = "wait"; |
---|
740 | return -1; |
---|
741 | } |
---|
742 | |
---|
743 | return 0; |
---|
744 | } |
---|
745 | |
---|
746 | /* Create a pipe. */ |
---|
747 | |
---|
748 | static int |
---|
749 | pex_unix_pipe (struct pex_obj *obj ATTRIBUTE_UNUSED, int *p, |
---|
750 | int binary ATTRIBUTE_UNUSED) |
---|
751 | { |
---|
752 | return pipe (p); |
---|
753 | } |
---|
754 | |
---|
755 | /* Get a FILE pointer to read from a file descriptor. */ |
---|
756 | |
---|
757 | static FILE * |
---|
758 | pex_unix_fdopenr (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd, |
---|
759 | int binary ATTRIBUTE_UNUSED) |
---|
760 | { |
---|
761 | return fdopen (fd, "r"); |
---|
762 | } |
---|
763 | |
---|
764 | static FILE * |
---|
765 | pex_unix_fdopenw (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd, |
---|
766 | int binary ATTRIBUTE_UNUSED) |
---|
767 | { |
---|
768 | if (fcntl (fd, F_SETFD, FD_CLOEXEC) < 0) |
---|
769 | return NULL; |
---|
770 | return fdopen (fd, "w"); |
---|
771 | } |
---|
772 | |
---|
773 | static void |
---|
774 | pex_unix_cleanup (struct pex_obj *obj ATTRIBUTE_UNUSED) |
---|
775 | { |
---|
776 | #if !defined (HAVE_WAIT4) && !defined (HAVE_WAITPID) |
---|
777 | while (obj->sysdep != NULL) |
---|
778 | { |
---|
779 | struct status_list *this; |
---|
780 | struct status_list *next; |
---|
781 | |
---|
782 | this = (struct status_list *) obj->sysdep; |
---|
783 | next = this->next; |
---|
784 | free (this); |
---|
785 | obj->sysdep = (void *) next; |
---|
786 | } |
---|
787 | #endif |
---|
788 | } |
---|