File: | build/libiberty/pex-unix.c |
Warning: | line 643, column 12 This assignment is prohibited after a successful vfork |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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-2023 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 "config.h" | |||
23 | #include "libiberty.h" | |||
24 | #include "pex-common.h" | |||
25 | #include "environ.h" | |||
26 | ||||
27 | #include <stdio.h> | |||
28 | #include <signal.h> | |||
29 | #include <errno(*__errno_location ()).h> | |||
30 | #ifdef NEED_DECLARATION_ERRNO | |||
31 | extern int errno(*__errno_location ()); | |||
32 | #endif | |||
33 | #ifdef HAVE_STDLIB_H1 | |||
34 | #include <stdlib.h> | |||
35 | #endif | |||
36 | #ifdef HAVE_STRING_H1 | |||
37 | #include <string.h> | |||
38 | #endif | |||
39 | #ifdef HAVE_UNISTD_H1 | |||
40 | #include <unistd.h> | |||
41 | #endif | |||
42 | ||||
43 | #include <sys/types.h> | |||
44 | ||||
45 | #ifdef HAVE_FCNTL_H1 | |||
46 | #include <fcntl.h> | |||
47 | #endif | |||
48 | #ifdef HAVE_SYS_WAIT_H1 | |||
49 | #include <sys/wait.h> | |||
50 | #endif | |||
51 | #ifdef HAVE_GETRUSAGE1 | |||
52 | #include <sys/time.h> | |||
53 | #include <sys/resource.h> | |||
54 | #endif | |||
55 | #ifdef HAVE_SYS_STAT_H1 | |||
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"vfork" "fork" | |||
64 | #else | |||
65 | # define VFORK_STRING"vfork" "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)char **ptr64 | |||
84 | { | |||
85 | int argc; | |||
86 | __char_ptr_char_ptr32 short_argv; | |||
87 | ||||
88 | /* Count number of arguments. */ | |||
89 | for (argc = 0; ptr64[argc] != NULL((void*)0); argc++) | |||
90 | ; | |||
91 | ||||
92 | /* Reallocate argv with 32 bit pointers. */ | |||
93 | short_argv = (__char_ptr_char_ptr32) decc$malloc | |||
94 | (sizeof (__char_ptr32) * (argc + 1)); | |||
95 | ||||
96 | for (argc = 0; ptr64[argc] != NULL((void*)0); argc++) | |||
97 | short_argv[argc] = (__char_ptr32) decc$strdup (ptr64[argc]); | |||
98 | ||||
99 | short_argv[argc] = (__char_ptr32) 0; | |||
100 | return short_argv; | |||
101 | ||||
102 | } | |||
103 | #else | |||
104 | #define to_ptr32(argv)argv argv | |||
105 | #endif | |||
106 | ||||
107 | /* File mode to use for private and world-readable files. */ | |||
108 | ||||
109 | #if defined (S_IRUSR0400) && defined (S_IWUSR0200) && defined (S_IRGRP(0400 >> 3)) && defined (S_IWGRP(0200 >> 3)) && defined (S_IROTH((0400 >> 3) >> 3)) && defined (S_IWOTH((0200 >> 3) >> 3)) | |||
110 | #define PUBLIC_MODE(0400 | 0200 | (0400 >> 3) | (0200 >> 3) | ((0400 >> 3) >> 3) | ((0200 >> 3) >> 3)) \ | |||
111 | (S_IRUSR0400 | S_IWUSR0200 | S_IRGRP(0400 >> 3) | S_IWGRP(0200 >> 3) | S_IROTH((0400 >> 3) >> 3) | S_IWOTH((0200 >> 3) >> 3)) | |||
112 | #else | |||
113 | #define PUBLIC_MODE(0400 | 0200 | (0400 >> 3) | (0200 >> 3) | ((0400 >> 3) >> 3) | ((0200 >> 3) >> 3)) 0666 | |||
114 | #endif | |||
115 | ||||
116 | /* Get the exit status of a particular process, and optionally get the | |||
117 | time that it took. This is simple if we have wait4, slightly | |||
118 | harder if we have waitpid, and is a pain if we only have wait. */ | |||
119 | ||||
120 | static pid_t pex_wait (struct pex_obj *, pid_t, int *, struct pex_time *); | |||
121 | ||||
122 | #ifdef HAVE_WAIT41 | |||
123 | ||||
124 | static pid_t | |||
125 | pex_wait (struct pex_obj *obj ATTRIBUTE_UNUSED__attribute__ ((__unused__)), pid_t pid, int *status, | |||
126 | struct pex_time *time) | |||
127 | { | |||
128 | pid_t ret; | |||
129 | struct rusage r; | |||
130 | ||||
131 | #ifdef HAVE_WAITPID1 | |||
132 | if (time == NULL((void*)0)) | |||
133 | return waitpid (pid, status, 0); | |||
134 | #endif | |||
135 | ||||
136 | ret = wait4 (pid, status, 0, &r); | |||
137 | ||||
138 | if (time != NULL((void*)0)) | |||
139 | { | |||
140 | time->user_seconds = r.ru_utime.tv_sec; | |||
141 | time->user_microseconds= r.ru_utime.tv_usec; | |||
142 | time->system_seconds = r.ru_stime.tv_sec; | |||
143 | time->system_microseconds= r.ru_stime.tv_usec; | |||
144 | } | |||
145 | ||||
146 | return ret; | |||
147 | } | |||
148 | ||||
149 | #else /* ! defined (HAVE_WAIT4) */ | |||
150 | ||||
151 | #ifdef HAVE_WAITPID1 | |||
152 | ||||
153 | #ifndef HAVE_GETRUSAGE1 | |||
154 | ||||
155 | static pid_t | |||
156 | pex_wait (struct pex_obj *obj ATTRIBUTE_UNUSED__attribute__ ((__unused__)), pid_t pid, int *status, | |||
157 | struct pex_time *time) | |||
158 | { | |||
159 | if (time != NULL((void*)0)) | |||
160 | memset (time, 0, sizeof (struct pex_time)); | |||
161 | return waitpid (pid, status, 0); | |||
162 | } | |||
163 | ||||
164 | #else /* defined (HAVE_GETRUSAGE) */ | |||
165 | ||||
166 | static pid_t | |||
167 | pex_wait (struct pex_obj *obj ATTRIBUTE_UNUSED__attribute__ ((__unused__)), pid_t pid, int *status, | |||
168 | struct pex_time *time) | |||
169 | { | |||
170 | struct rusage r1, r2; | |||
171 | pid_t ret; | |||
172 | ||||
173 | if (time == NULL((void*)0)) | |||
174 | return waitpid (pid, status, 0); | |||
175 | ||||
176 | getrusage (RUSAGE_CHILDRENRUSAGE_CHILDREN, &r1); | |||
177 | ||||
178 | ret = waitpid (pid, status, 0); | |||
179 | if (ret < 0) | |||
180 | return ret; | |||
181 | ||||
182 | getrusage (RUSAGE_CHILDRENRUSAGE_CHILDREN, &r2); | |||
183 | ||||
184 | time->user_seconds = r2.ru_utime.tv_sec - r1.ru_utime.tv_sec; | |||
185 | time->user_microseconds = r2.ru_utime.tv_usec - r1.ru_utime.tv_usec; | |||
186 | if (r2.ru_utime.tv_usec < r1.ru_utime.tv_usec) | |||
187 | { | |||
188 | --time->user_seconds; | |||
189 | time->user_microseconds += 1000000; | |||
190 | } | |||
191 | ||||
192 | time->system_seconds = r2.ru_stime.tv_sec - r1.ru_stime.tv_sec; | |||
193 | time->system_microseconds = r2.ru_stime.tv_usec - r1.ru_stime.tv_usec; | |||
194 | if (r2.ru_stime.tv_usec < r1.ru_stime.tv_usec) | |||
195 | { | |||
196 | --time->system_seconds; | |||
197 | time->system_microseconds += 1000000; | |||
198 | } | |||
199 | ||||
200 | return ret; | |||
201 | } | |||
202 | ||||
203 | #endif /* defined (HAVE_GETRUSAGE) */ | |||
204 | ||||
205 | #else /* ! defined (HAVE_WAITPID) */ | |||
206 | ||||
207 | struct status_list | |||
208 | { | |||
209 | struct status_list *next; | |||
210 | pid_t pid; | |||
211 | int status; | |||
212 | struct pex_time time; | |||
213 | }; | |||
214 | ||||
215 | static pid_t | |||
216 | pex_wait (struct pex_obj *obj, pid_t pid, int *status, struct pex_time *time) | |||
217 | { | |||
218 | struct status_list **pp; | |||
219 | ||||
220 | for (pp = (struct status_list **) &obj->sysdep; | |||
221 | *pp != NULL((void*)0); | |||
222 | pp = &(*pp)->next) | |||
223 | { | |||
224 | if ((*pp)->pid == pid) | |||
225 | { | |||
226 | struct status_list *p; | |||
227 | ||||
228 | p = *pp; | |||
229 | *status = p->status; | |||
230 | if (time != NULL((void*)0)) | |||
231 | *time = p->time; | |||
232 | *pp = p->next; | |||
233 | free (p); | |||
234 | return pid; | |||
235 | } | |||
236 | } | |||
237 | ||||
238 | while (1) | |||
239 | { | |||
240 | pid_t cpid; | |||
241 | struct status_list *psl; | |||
242 | struct pex_time pt; | |||
243 | #ifdef HAVE_GETRUSAGE1 | |||
244 | struct rusage r1, r2; | |||
245 | #endif | |||
246 | ||||
247 | if (time != NULL((void*)0)) | |||
248 | { | |||
249 | #ifdef HAVE_GETRUSAGE1 | |||
250 | getrusage (RUSAGE_CHILDRENRUSAGE_CHILDREN, &r1); | |||
251 | #else | |||
252 | memset (&pt, 0, sizeof (struct pex_time)); | |||
253 | #endif | |||
254 | } | |||
255 | ||||
256 | cpid = wait (status); | |||
257 | ||||
258 | #ifdef HAVE_GETRUSAGE1 | |||
259 | if (time != NULL((void*)0) && cpid >= 0) | |||
260 | { | |||
261 | getrusage (RUSAGE_CHILDRENRUSAGE_CHILDREN, &r2); | |||
262 | ||||
263 | pt.user_seconds = r2.ru_utime.tv_sec - r1.ru_utime.tv_sec; | |||
264 | pt.user_microseconds = r2.ru_utime.tv_usec - r1.ru_utime.tv_usec; | |||
265 | if (pt.user_microseconds < 0) | |||
266 | { | |||
267 | --pt.user_seconds; | |||
268 | pt.user_microseconds += 1000000; | |||
269 | } | |||
270 | ||||
271 | pt.system_seconds = r2.ru_stime.tv_sec - r1.ru_stime.tv_sec; | |||
272 | pt.system_microseconds = r2.ru_stime.tv_usec - r1.ru_stime.tv_usec; | |||
273 | if (pt.system_microseconds < 0) | |||
274 | { | |||
275 | --pt.system_seconds; | |||
276 | pt.system_microseconds += 1000000; | |||
277 | } | |||
278 | } | |||
279 | #endif | |||
280 | ||||
281 | if (cpid < 0 || cpid == pid) | |||
282 | { | |||
283 | if (time != NULL((void*)0)) | |||
284 | *time = pt; | |||
285 | return cpid; | |||
286 | } | |||
287 | ||||
288 | psl = XNEW (struct status_list)((struct status_list *) xmalloc (sizeof (struct status_list)) ); | |||
289 | psl->pid = cpid; | |||
290 | psl->status = *status; | |||
291 | if (time != NULL((void*)0)) | |||
292 | psl->time = pt; | |||
293 | psl->next = (struct status_list *) obj->sysdep; | |||
294 | obj->sysdep = (void *) psl; | |||
295 | } | |||
296 | } | |||
297 | ||||
298 | #endif /* ! defined (HAVE_WAITPID) */ | |||
299 | #endif /* ! defined (HAVE_WAIT4) */ | |||
300 | ||||
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, 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__attribute__ ((__unused__)), const char *name, | |||
342 | int binary ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
343 | { | |||
344 | return open (name, O_RDONLY00); | |||
345 | } | |||
346 | ||||
347 | /* Open a file for writing. */ | |||
348 | ||||
349 | static int | |||
350 | pex_unix_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED__attribute__ ((__unused__)), const char *name, | |||
351 | int binary ATTRIBUTE_UNUSED__attribute__ ((__unused__)), int append) | |||
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_WRONLY01 | O_CREAT0100 | |||
356 | | (append ? O_APPEND02000 : O_TRUNC01000), PUBLIC_MODE(0400 | 0200 | (0400 >> 3) | (0200 >> 3) | ((0400 >> 3) >> 3) | ((0200 >> 3) >> 3))); | |||
357 | } | |||
358 | ||||
359 | /* Close a file. */ | |||
360 | ||||
361 | static int | |||
362 | pex_unix_close (struct pex_obj *obj ATTRIBUTE_UNUSED__attribute__ ((__unused__)), int fd) | |||
363 | { | |||
364 | return close (fd); | |||
365 | } | |||
366 | ||||
367 | /* Execute a child. */ | |||
368 | ||||
369 | #if defined(HAVE_SPAWNVE) && defined(HAVE_SPAWNVPE) | |||
370 | /* Implementation of pex->exec_child using the Cygwin spawn operation. */ | |||
371 | ||||
372 | /* Subroutine of pex_unix_exec_child. Move OLD_FD to a new file descriptor | |||
373 | to be stored in *PNEW_FD, save the flags in *PFLAGS, and arrange for the | |||
374 | saved copy to be close-on-exec. Move CHILD_FD into OLD_FD. If CHILD_FD | |||
375 | is -1, OLD_FD is to be closed. Return -1 on error. */ | |||
376 | ||||
377 | static int | |||
378 | save_and_install_fd(int *pnew_fd, int *pflags, int old_fd, int child_fd) | |||
379 | { | |||
380 | int new_fd, flags; | |||
381 | ||||
382 | flags = fcntl (old_fd, F_GETFD1); | |||
383 | ||||
384 | /* If we could not retrieve the flags, then OLD_FD was not open. */ | |||
385 | if (flags < 0) | |||
386 | { | |||
387 | new_fd = -1, flags = 0; | |||
388 | if (child_fd >= 0 && dup2 (child_fd, old_fd) < 0) | |||
389 | return -1; | |||
390 | } | |||
391 | /* If we wish to close OLD_FD, just mark it CLOEXEC. */ | |||
392 | else if (child_fd == -1) | |||
393 | { | |||
394 | new_fd = old_fd; | |||
395 | if ((flags & FD_CLOEXEC1) == 0 && fcntl (old_fd, F_SETFD2, FD_CLOEXEC1) < 0) | |||
396 | return -1; | |||
397 | } | |||
398 | /* Otherwise we need to save a copy of OLD_FD before installing CHILD_FD. */ | |||
399 | else | |||
400 | { | |||
401 | #ifdef F_DUPFD_CLOEXEC1030 | |||
402 | new_fd = fcntl (old_fd, F_DUPFD_CLOEXEC1030, 3); | |||
403 | if (new_fd < 0) | |||
404 | return -1; | |||
405 | #else | |||
406 | /* Prefer F_DUPFD over dup in order to avoid getting a new fd | |||
407 | in the range 0-2, right where a new stderr fd might get put. */ | |||
408 | new_fd = fcntl (old_fd, F_DUPFD0, 3); | |||
409 | if (new_fd < 0) | |||
410 | return -1; | |||
411 | if (fcntl (new_fd, F_SETFD2, FD_CLOEXEC1) < 0) | |||
412 | return -1; | |||
413 | #endif | |||
414 | if (dup2 (child_fd, old_fd) < 0) | |||
415 | return -1; | |||
416 | } | |||
417 | ||||
418 | *pflags = flags; | |||
419 | if (pnew_fd) | |||
420 | *pnew_fd = new_fd; | |||
421 | else if (new_fd != old_fd) | |||
422 | abort (); | |||
423 | ||||
424 | return 0; | |||
425 | } | |||
426 | ||||
427 | /* Subroutine of pex_unix_exec_child. Move SAVE_FD back to OLD_FD | |||
428 | restoring FLAGS. If SAVE_FD < 0, OLD_FD is to be closed. */ | |||
429 | ||||
430 | static int | |||
431 | restore_fd(int old_fd, int save_fd, int flags) | |||
432 | { | |||
433 | /* For SAVE_FD < 0, all we have to do is restore the | |||
434 | "closed-ness" of the original. */ | |||
435 | if (save_fd < 0) | |||
436 | return close (old_fd); | |||
437 | ||||
438 | /* For SAVE_FD == OLD_FD, all we have to do is restore the | |||
439 | original setting of the CLOEXEC flag. */ | |||
440 | if (save_fd == old_fd) | |||
441 | { | |||
442 | if (flags & FD_CLOEXEC1) | |||
443 | return 0; | |||
444 | return fcntl (old_fd, F_SETFD2, flags); | |||
445 | } | |||
446 | ||||
447 | /* Otherwise we have to move the descriptor back, restore the flags, | |||
448 | and close the saved copy. */ | |||
449 | #ifdef HAVE_DUP31 | |||
450 | if (flags == FD_CLOEXEC1) | |||
451 | { | |||
452 | if (dup3 (save_fd, old_fd, O_CLOEXEC02000000) < 0) | |||
453 | return -1; | |||
454 | } | |||
455 | else | |||
456 | #endif | |||
457 | { | |||
458 | if (dup2 (save_fd, old_fd) < 0) | |||
459 | return -1; | |||
460 | if (flags != 0 && fcntl (old_fd, F_SETFD2, flags) < 0) | |||
461 | return -1; | |||
462 | } | |||
463 | return close (save_fd); | |||
464 | } | |||
465 | ||||
466 | static pid_t | |||
467 | pex_unix_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED__attribute__ ((__unused__)), | |||
468 | int flags, const char *executable, | |||
469 | char * const * argv, char * const * env, | |||
470 | int in, int out, int errdes, int toclose, | |||
471 | const char **errmsg, int *err) | |||
472 | { | |||
473 | int fl_in = 0, fl_out = 0, fl_err = 0, fl_tc = 0; | |||
474 | int save_in = -1, save_out = -1, save_err = -1; | |||
475 | int max, retries; | |||
476 | pid_t pid; | |||
477 | ||||
478 | if (flags & PEX_STDERR_TO_STDOUT0x8) | |||
479 | errdes = out; | |||
480 | ||||
481 | /* We need the three standard file descriptors to be set up as for | |||
482 | the child before we perform the spawn. The file descriptors for | |||
483 | the parent need to be moved and marked for close-on-exec. */ | |||
484 | if (in != STDIN_FILE_NO0 | |||
485 | && save_and_install_fd (&save_in, &fl_in, STDIN_FILE_NO0, in) < 0) | |||
486 | goto error_dup2; | |||
487 | if (out != STDOUT_FILE_NO1 | |||
488 | && save_and_install_fd (&save_out, &fl_out, STDOUT_FILE_NO1, out) < 0) | |||
489 | goto error_dup2; | |||
490 | if (errdes != STDERR_FILE_NO2 | |||
491 | && save_and_install_fd (&save_err, &fl_err, STDERR_FILE_NO2, errdes) < 0) | |||
492 | goto error_dup2; | |||
493 | if (toclose >= 0 | |||
494 | && save_and_install_fd (NULL((void*)0), &fl_tc, toclose, -1) < 0) | |||
495 | goto error_dup2; | |||
496 | ||||
497 | /* Now that we've moved the file descriptors for the child into place, | |||
498 | close the originals. Be careful not to close any of the standard | |||
499 | file descriptors that we just set up. */ | |||
500 | max = -1; | |||
501 | if (errdes >= 0) | |||
502 | max = STDERR_FILE_NO2; | |||
503 | else if (out >= 0) | |||
504 | max = STDOUT_FILE_NO1; | |||
505 | else if (in >= 0) | |||
506 | max = STDIN_FILE_NO0; | |||
507 | if (in > max) | |||
508 | close (in); | |||
509 | if (out > max) | |||
510 | close (out); | |||
511 | if (errdes > max && errdes != out) | |||
512 | close (errdes); | |||
513 | ||||
514 | /* If we were not given an environment, use the global environment. */ | |||
515 | if (env == NULL((void*)0)) | |||
516 | env = environ; | |||
517 | ||||
518 | /* Launch the program. If we get EAGAIN (normally out of pid's), try | |||
519 | again a few times with increasing backoff times. */ | |||
520 | retries = 0; | |||
521 | while (1) | |||
522 | { | |||
523 | typedef const char * const *cc_cp; | |||
524 | ||||
525 | if (flags & PEX_SEARCH0x2) | |||
526 | pid = spawnvpe (_P_NOWAITO, executable, (cc_cp)argv, (cc_cp)env); | |||
527 | else | |||
528 | pid = spawnve (_P_NOWAITO, executable, (cc_cp)argv, (cc_cp)env); | |||
529 | ||||
530 | if (pid > 0) | |||
531 | break; | |||
532 | ||||
533 | *err = errno(*__errno_location ()); | |||
534 | *errmsg = "spawn"; | |||
535 | if (errno(*__errno_location ()) != EAGAIN11 || ++retries == 4) | |||
536 | return (pid_t) -1; | |||
537 | sleep (1 << retries); | |||
538 | } | |||
539 | ||||
540 | /* Success. Restore the parent's file descriptors that we saved above. */ | |||
541 | if (toclose >= 0 | |||
542 | && restore_fd (toclose, toclose, fl_tc) < 0) | |||
543 | goto error_dup2; | |||
544 | if (in != STDIN_FILE_NO0 | |||
545 | && restore_fd (STDIN_FILE_NO0, save_in, fl_in) < 0) | |||
546 | goto error_dup2; | |||
547 | if (out != STDOUT_FILE_NO1 | |||
548 | && restore_fd (STDOUT_FILE_NO1, save_out, fl_out) < 0) | |||
549 | goto error_dup2; | |||
550 | if (errdes != STDERR_FILE_NO2 | |||
551 | && restore_fd (STDERR_FILE_NO2, save_err, fl_err) < 0) | |||
552 | goto error_dup2; | |||
553 | ||||
554 | return pid; | |||
555 | ||||
556 | error_dup2: | |||
557 | *err = errno(*__errno_location ()); | |||
558 | *errmsg = "dup2"; | |||
559 | return (pid_t) -1; | |||
560 | } | |||
561 | ||||
562 | #else | |||
563 | /* Implementation of pex->exec_child using standard vfork + exec. */ | |||
564 | ||||
565 | static pid_t | |||
566 | pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable, | |||
567 | char * const * argv, char * const * env, | |||
568 | int in, int out, int errdes, | |||
569 | int toclose, const char **errmsg, int *err) | |||
570 | { | |||
571 | pid_t pid = -1; | |||
572 | /* Tuple to communicate error from child to parent. We can safely | |||
573 | transfer string literal pointers as both run with identical | |||
574 | address mappings. */ | |||
575 | struct fn_err | |||
576 | { | |||
577 | const char *fn; | |||
578 | int err; | |||
579 | }; | |||
580 | volatile int do_pipe = 0; | |||
581 | volatile int pipes[2]; /* [0]:reader,[1]:writer. */ | |||
582 | #ifdef O_CLOEXEC02000000 | |||
583 | do_pipe = 1; | |||
584 | #endif | |||
585 | if (do_pipe
| |||
| ||||
586 | { | |||
587 | #ifdef HAVE_PIPE21 | |||
588 | if (pipe2 ((int *)pipes, O_CLOEXEC02000000)) | |||
589 | do_pipe = 0; | |||
590 | #else | |||
591 | if (pipe ((int *)pipes)) | |||
592 | do_pipe = 0; | |||
593 | else | |||
594 | { | |||
595 | if (fcntl (pipes[1], F_SETFD2, FD_CLOEXEC1) == -1) | |||
596 | { | |||
597 | close (pipes[0]); | |||
598 | close (pipes[1]); | |||
599 | do_pipe = 0; | |||
600 | } | |||
601 | } | |||
602 | #endif | |||
603 | } | |||
604 | ||||
605 | /* We declare these to be volatile to avoid warnings from gcc about | |||
606 | them being clobbered by vfork. */ | |||
607 | volatile int sleep_interval = 1; | |||
608 | volatile int retries; | |||
609 | ||||
610 | /* We vfork and then set environ in the child before calling execvp. | |||
611 | This clobbers the parent's environ so we need to restore it. | |||
612 | It would be nice to use one of the exec* functions that takes an | |||
613 | environment as a parameter, but that may have portability | |||
614 | issues. It is marked volatile so the child doesn't consider it a | |||
615 | dead variable and therefore clobber where ever it is stored. */ | |||
616 | char **volatile save_environ = environ; | |||
617 | ||||
618 | for (retries = 0; retries < 4; ++retries) | |||
619 | { | |||
620 | pid = vfork (); | |||
621 | if (pid
| |||
622 | break; | |||
623 | sleep (sleep_interval); | |||
624 | sleep_interval *= 2; | |||
625 | } | |||
626 | ||||
627 | switch (pid) | |||
628 | { | |||
629 | case -1: | |||
630 | if (do_pipe) | |||
631 | { | |||
632 | close (pipes[0]); | |||
633 | close (pipes[1]); | |||
634 | } | |||
635 | *err = errno(*__errno_location ()); | |||
636 | *errmsg = VFORK_STRING"vfork"; | |||
637 | return (pid_t) -1; | |||
638 | ||||
639 | case 0: | |||
640 | /* Child process. */ | |||
641 | { | |||
642 | struct fn_err failed; | |||
643 | failed.fn = NULL((void*)0); | |||
| ||||
644 | ||||
645 | if (do_pipe) | |||
646 | close (pipes[0]); | |||
647 | if (!failed.fn && in != STDIN_FILE_NO0) | |||
648 | { | |||
649 | if (dup2 (in, STDIN_FILE_NO0) < 0) | |||
650 | failed.fn = "dup2", failed.err = errno(*__errno_location ()); | |||
651 | else if (close (in) < 0) | |||
652 | failed.fn = "close", failed.err = errno(*__errno_location ()); | |||
653 | } | |||
654 | if (!failed.fn && out != STDOUT_FILE_NO1) | |||
655 | { | |||
656 | if (dup2 (out, STDOUT_FILE_NO1) < 0) | |||
657 | failed.fn = "dup2", failed.err = errno(*__errno_location ()); | |||
658 | else if (close (out) < 0) | |||
659 | failed.fn = "close", failed.err = errno(*__errno_location ()); | |||
660 | } | |||
661 | if (!failed.fn && errdes != STDERR_FILE_NO2) | |||
662 | { | |||
663 | if (dup2 (errdes, STDERR_FILE_NO2) < 0) | |||
664 | failed.fn = "dup2", failed.err = errno(*__errno_location ()); | |||
665 | else if (close (errdes) < 0) | |||
666 | failed.fn = "close", failed.err = errno(*__errno_location ()); | |||
667 | } | |||
668 | if (!failed.fn && toclose >= 0) | |||
669 | { | |||
670 | if (close (toclose) < 0) | |||
671 | failed.fn = "close", failed.err = errno(*__errno_location ()); | |||
672 | } | |||
673 | if (!failed.fn && (flags & PEX_STDERR_TO_STDOUT0x8) != 0) | |||
674 | { | |||
675 | if (dup2 (STDOUT_FILE_NO1, STDERR_FILE_NO2) < 0) | |||
676 | failed.fn = "dup2", failed.err = errno(*__errno_location ()); | |||
677 | } | |||
678 | if (!failed.fn) | |||
679 | { | |||
680 | if (env) | |||
681 | /* NOTE: In a standard vfork implementation this clobbers | |||
682 | the parent's copy of environ "too" (in reality there's | |||
683 | only one copy). This is ok as we restore it below. */ | |||
684 | environ = (char**) env; | |||
685 | if ((flags & PEX_SEARCH0x2) != 0) | |||
686 | { | |||
687 | execvp (executable, to_ptr32 (argv)argv); | |||
688 | failed.fn = "execvp", failed.err = errno(*__errno_location ()); | |||
689 | } | |||
690 | else | |||
691 | { | |||
692 | execv (executable, to_ptr32 (argv)argv); | |||
693 | failed.fn = "execv", failed.err = errno(*__errno_location ()); | |||
694 | } | |||
695 | } | |||
696 | ||||
697 | /* Something failed, report an error. We don't use stdio | |||
698 | routines, because we might be here due to a vfork call. */ | |||
699 | ssize_t retval = 0; | |||
700 | ||||
701 | if (!do_pipe | |||
702 | || write (pipes[1], &failed, sizeof (failed)) != sizeof (failed)) | |||
703 | { | |||
704 | /* The parent will not see our scream above, so write to | |||
705 | stdout. */ | |||
706 | #define writeerr(s) (retval |= write (STDERR_FILE_NO2, s, strlen (s))) | |||
707 | writeerr (obj->pname); | |||
708 | writeerr (": error trying to exec '"); | |||
709 | writeerr (executable); | |||
710 | writeerr ("': "); | |||
711 | writeerr (failed.fn); | |||
712 | writeerr (": "); | |||
713 | writeerr (xstrerror (failed.err)); | |||
714 | writeerr ("\n"); | |||
715 | #undef writeerr | |||
716 | } | |||
717 | ||||
718 | /* Exit with -2 if the error output failed, too. */ | |||
719 | _exit (retval < 0 ? -2 : -1); | |||
720 | } | |||
721 | /* NOTREACHED */ | |||
722 | return (pid_t) -1; | |||
723 | ||||
724 | default: | |||
725 | /* Parent process. */ | |||
726 | { | |||
727 | /* Restore environ. Note that the parent either doesn't run | |||
728 | until the child execs/exits (standard vfork behaviour), or | |||
729 | if it does run then vfork is behaving more like fork. In | |||
730 | either case we needn't worry about clobbering the child's | |||
731 | copy of environ. */ | |||
732 | environ = save_environ; | |||
733 | ||||
734 | struct fn_err failed; | |||
735 | failed.fn = NULL((void*)0); | |||
736 | if (do_pipe) | |||
737 | { | |||
738 | close (pipes[1]); | |||
739 | ssize_t len = read (pipes[0], &failed, sizeof (failed)); | |||
740 | if (len < 0) | |||
741 | failed.fn = NULL((void*)0); | |||
742 | close (pipes[0]); | |||
743 | } | |||
744 | ||||
745 | if (!failed.fn && in != STDIN_FILE_NO0) | |||
746 | if (close (in) < 0) | |||
747 | failed.fn = "close", failed.err = errno(*__errno_location ()); | |||
748 | if (!failed.fn && out != STDOUT_FILE_NO1) | |||
749 | if (close (out) < 0) | |||
750 | failed.fn = "close", failed.err = errno(*__errno_location ()); | |||
751 | if (!failed.fn && errdes != STDERR_FILE_NO2) | |||
752 | if (close (errdes) < 0) | |||
753 | failed.fn = "close", failed.err = errno(*__errno_location ()); | |||
754 | ||||
755 | if (failed.fn) | |||
756 | { | |||
757 | *err = failed.err; | |||
758 | *errmsg = failed.fn; | |||
759 | return (pid_t) -1; | |||
760 | } | |||
761 | } | |||
762 | return pid; | |||
763 | } | |||
764 | } | |||
765 | #endif /* SPAWN */ | |||
766 | ||||
767 | /* Wait for a child process to complete. */ | |||
768 | ||||
769 | static int | |||
770 | pex_unix_wait (struct pex_obj *obj, pid_t pid, int *status, | |||
771 | struct pex_time *time, int done, const char **errmsg, | |||
772 | int *err) | |||
773 | { | |||
774 | /* If we are cleaning up when the caller didn't retrieve process | |||
775 | status for some reason, encourage the process to go away. */ | |||
776 | if (done) | |||
777 | kill (pid, SIGTERM15); | |||
778 | ||||
779 | if (pex_wait (obj, pid, status, time) < 0) | |||
780 | { | |||
781 | *err = errno(*__errno_location ()); | |||
782 | *errmsg = "wait"; | |||
783 | return -1; | |||
784 | } | |||
785 | ||||
786 | return 0; | |||
787 | } | |||
788 | ||||
789 | /* Create a pipe. */ | |||
790 | ||||
791 | static int | |||
792 | pex_unix_pipe (struct pex_obj *obj ATTRIBUTE_UNUSED__attribute__ ((__unused__)), int *p, | |||
793 | int binary ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
794 | { | |||
795 | return pipe (p); | |||
796 | } | |||
797 | ||||
798 | /* Get a FILE pointer to read from a file descriptor. */ | |||
799 | ||||
800 | static FILE * | |||
801 | pex_unix_fdopenr (struct pex_obj *obj ATTRIBUTE_UNUSED__attribute__ ((__unused__)), int fd, | |||
802 | int binary ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
803 | { | |||
804 | return fdopen (fd, "r"); | |||
805 | } | |||
806 | ||||
807 | static FILE * | |||
808 | pex_unix_fdopenw (struct pex_obj *obj ATTRIBUTE_UNUSED__attribute__ ((__unused__)), int fd, | |||
809 | int binary ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
810 | { | |||
811 | if (fcntl (fd, F_SETFD2, FD_CLOEXEC1) < 0) | |||
812 | return NULL((void*)0); | |||
813 | return fdopen (fd, "w"); | |||
814 | } | |||
815 | ||||
816 | static void | |||
817 | pex_unix_cleanup (struct pex_obj *obj ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
818 | { | |||
819 | #if !defined (HAVE_WAIT41) && !defined (HAVE_WAITPID1) | |||
820 | while (obj->sysdep != NULL((void*)0)) | |||
821 | { | |||
822 | struct status_list *this; | |||
823 | struct status_list *next; | |||
824 | ||||
825 | this = (struct status_list *) obj->sysdep; | |||
826 | next = this->next; | |||
827 | free (this); | |||
828 | obj->sysdep = (void *) next; | |||
829 | } | |||
830 | #endif | |||
831 | } |