Mercurial > hg > CbC > CbC_gcc
annotate libiberty/pex-unix.c @ 158:494b0b89df80 default tip
...
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 25 May 2020 18:13:55 +0900 |
parents | 1830386684a0 |
children |
rev | line source |
---|---|
0 | 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). | |
145 | 4 Copyright (C) 1996-2020 Free Software Foundation, Inc. |
0 | 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" | |
111 | 25 #include "environ.h" |
0 | 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 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
58 #ifdef HAVE_PROCESS_H |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
59 #include <process.h> |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
60 #endif |
0 | 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 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
70 #if defined(VMS) && defined (__LONG_POINTERS) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
71 #ifndef __CHAR_PTR32 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
72 typedef char * __char_ptr32 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
73 __attribute__ ((mode (SI))); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
74 #endif |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
75 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
76 typedef __char_ptr32 *__char_ptr_char_ptr32 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
77 __attribute__ ((mode (SI))); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
78 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
79 /* Return a 32 bit pointer to an array of 32 bit pointers |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
80 given a 64 bit pointer to an array of 64 bit pointers. */ |
0 | 81 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
82 static __char_ptr_char_ptr32 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
83 to_ptr32 (char **ptr64) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
84 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
85 int argc; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
86 __char_ptr_char_ptr32 short_argv; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
87 |
111 | 88 /* Count number of arguments. */ |
89 for (argc = 0; ptr64[argc] != NULL; argc++) | |
90 ; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
91 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
92 /* Reallocate argv with 32 bit pointers. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
93 short_argv = (__char_ptr_char_ptr32) decc$malloc |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
94 (sizeof (__char_ptr32) * (argc + 1)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
95 |
111 | 96 for (argc = 0; ptr64[argc] != NULL; argc++) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
97 short_argv[argc] = (__char_ptr32) decc$strdup (ptr64[argc]); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
98 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
99 short_argv[argc] = (__char_ptr32) 0; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
100 return short_argv; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
101 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
102 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
103 #else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
104 #define to_ptr32(argv) argv |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
105 #endif |
0 | 106 |
107 /* File mode to use for private and world-readable files. */ | |
108 | |
109 #if defined (S_IRUSR) && defined (S_IWUSR) && defined (S_IRGRP) && defined (S_IWGRP) && defined (S_IROTH) && defined (S_IWOTH) | |
110 #define PUBLIC_MODE \ | |
111 (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) | |
112 #else | |
113 #define PUBLIC_MODE 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_WAIT4 | |
123 | |
124 static pid_t | |
125 pex_wait (struct pex_obj *obj 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_WAITPID | |
132 if (time == NULL) | |
133 return waitpid (pid, status, 0); | |
134 #endif | |
135 | |
136 ret = wait4 (pid, status, 0, &r); | |
137 | |
138 if (time != NULL) | |
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_WAITPID | |
152 | |
153 #ifndef HAVE_GETRUSAGE | |
154 | |
155 static pid_t | |
156 pex_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid, int *status, | |
157 struct pex_time *time) | |
158 { | |
159 if (time != NULL) | |
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, 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) | |
174 return waitpid (pid, status, 0); | |
175 | |
176 getrusage (RUSAGE_CHILDREN, &r1); | |
177 | |
178 ret = waitpid (pid, status, 0); | |
179 if (ret < 0) | |
180 return ret; | |
181 | |
182 getrusage (RUSAGE_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; | |
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) | |
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_GETRUSAGE | |
244 struct rusage r1, r2; | |
245 #endif | |
246 | |
247 if (time != NULL) | |
248 { | |
249 #ifdef HAVE_GETRUSAGE | |
250 getrusage (RUSAGE_CHILDREN, &r1); | |
251 #else | |
252 memset (&pt, 0, sizeof (struct pex_time)); | |
253 #endif | |
254 } | |
255 | |
256 cpid = wait (status); | |
257 | |
258 #ifdef HAVE_GETRUSAGE | |
259 if (time != NULL && cpid >= 0) | |
260 { | |
261 getrusage (RUSAGE_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) | |
284 *time = pt; | |
285 return cpid; | |
286 } | |
287 | |
288 psl = XNEW (struct status_list); | |
289 psl->pid = cpid; | |
290 psl->status = *status; | |
291 if (time != NULL) | |
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); | |
111 | 302 static int pex_unix_open_write (struct pex_obj *, const char *, int, int); |
0 | 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, | |
111 | 351 int binary ATTRIBUTE_UNUSED, int append) |
0 | 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. */ | |
111 | 355 return open (name, O_WRONLY | O_CREAT |
356 | (append ? O_APPEND : O_TRUNC), PUBLIC_MODE); | |
0 | 357 } |
358 | |
359 /* Close a file. */ | |
360 | |
361 static int | |
362 pex_unix_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd) | |
363 { | |
364 return close (fd); | |
365 } | |
366 | |
367 /* Execute a child. */ | |
368 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
369 #if defined(HAVE_SPAWNVE) && defined(HAVE_SPAWNVPE) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
370 /* Implementation of pex->exec_child using the Cygwin spawn operation. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
371 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
372 /* Subroutine of pex_unix_exec_child. Move OLD_FD to a new file descriptor |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
373 to be stored in *PNEW_FD, save the flags in *PFLAGS, and arrange for the |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
374 saved copy to be close-on-exec. Move CHILD_FD into OLD_FD. If CHILD_FD |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
375 is -1, OLD_FD is to be closed. Return -1 on error. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
376 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
377 static int |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
378 save_and_install_fd(int *pnew_fd, int *pflags, int old_fd, int child_fd) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
379 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
380 int new_fd, flags; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
381 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
382 flags = fcntl (old_fd, F_GETFD); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
383 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
384 /* If we could not retrieve the flags, then OLD_FD was not open. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
385 if (flags < 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
386 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
387 new_fd = -1, flags = 0; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
388 if (child_fd >= 0 && dup2 (child_fd, old_fd) < 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
389 return -1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
390 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
391 /* If we wish to close OLD_FD, just mark it CLOEXEC. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
392 else if (child_fd == -1) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
393 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
394 new_fd = old_fd; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
395 if ((flags & FD_CLOEXEC) == 0 && fcntl (old_fd, F_SETFD, FD_CLOEXEC) < 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
396 return -1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
397 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
398 /* Otherwise we need to save a copy of OLD_FD before installing CHILD_FD. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
399 else |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
400 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
401 #ifdef F_DUPFD_CLOEXEC |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
402 new_fd = fcntl (old_fd, F_DUPFD_CLOEXEC, 3); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
403 if (new_fd < 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
404 return -1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
405 #else |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
406 /* Prefer F_DUPFD over dup in order to avoid getting a new fd |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
407 in the range 0-2, right where a new stderr fd might get put. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
408 new_fd = fcntl (old_fd, F_DUPFD, 3); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
409 if (new_fd < 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
410 return -1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
411 if (fcntl (new_fd, F_SETFD, FD_CLOEXEC) < 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
412 return -1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
413 #endif |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
414 if (dup2 (child_fd, old_fd) < 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
415 return -1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
416 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
417 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
418 *pflags = flags; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
419 if (pnew_fd) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
420 *pnew_fd = new_fd; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
421 else if (new_fd != old_fd) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
422 abort (); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
423 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
424 return 0; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
425 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
426 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
427 /* Subroutine of pex_unix_exec_child. Move SAVE_FD back to OLD_FD |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
428 restoring FLAGS. If SAVE_FD < 0, OLD_FD is to be closed. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
429 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
430 static int |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
431 restore_fd(int old_fd, int save_fd, int flags) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
432 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
433 /* For SAVE_FD < 0, all we have to do is restore the |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
434 "closed-ness" of the original. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
435 if (save_fd < 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
436 return close (old_fd); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
437 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
438 /* For SAVE_FD == OLD_FD, all we have to do is restore the |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
439 original setting of the CLOEXEC flag. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
440 if (save_fd == old_fd) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
441 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
442 if (flags & FD_CLOEXEC) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
443 return 0; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
444 return fcntl (old_fd, F_SETFD, flags); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
445 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
446 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
447 /* Otherwise we have to move the descriptor back, restore the flags, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
448 and close the saved copy. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
449 #ifdef HAVE_DUP3 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
450 if (flags == FD_CLOEXEC) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
451 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
452 if (dup3 (save_fd, old_fd, O_CLOEXEC) < 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
453 return -1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
454 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
455 else |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
456 #endif |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
457 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
458 if (dup2 (save_fd, old_fd) < 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
459 return -1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
460 if (flags != 0 && fcntl (old_fd, F_SETFD, flags) < 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
461 return -1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
462 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
463 return close (save_fd); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
464 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
465 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
466 static pid_t |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
467 pex_unix_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
468 int flags, const char *executable, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
469 char * const * argv, char * const * env, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
470 int in, int out, int errdes, int toclose, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
471 const char **errmsg, int *err) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
472 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
473 int fl_in = 0, fl_out = 0, fl_err = 0, fl_tc = 0; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
474 int save_in = -1, save_out = -1, save_err = -1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
475 int max, retries; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
476 pid_t pid; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
477 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
478 if (flags & PEX_STDERR_TO_STDOUT) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
479 errdes = out; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
480 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
481 /* We need the three standard file descriptors to be set up as for |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
482 the child before we perform the spawn. The file descriptors for |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
483 the parent need to be moved and marked for close-on-exec. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
484 if (in != STDIN_FILE_NO |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
485 && save_and_install_fd (&save_in, &fl_in, STDIN_FILE_NO, in) < 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
486 goto error_dup2; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
487 if (out != STDOUT_FILE_NO |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
488 && save_and_install_fd (&save_out, &fl_out, STDOUT_FILE_NO, out) < 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
489 goto error_dup2; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
490 if (errdes != STDERR_FILE_NO |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
491 && save_and_install_fd (&save_err, &fl_err, STDERR_FILE_NO, errdes) < 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
492 goto error_dup2; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
493 if (toclose >= 0 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
494 && save_and_install_fd (NULL, &fl_tc, toclose, -1) < 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
495 goto error_dup2; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
496 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
497 /* Now that we've moved the file descriptors for the child into place, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
498 close the originals. Be careful not to close any of the standard |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
499 file descriptors that we just set up. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
500 max = -1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
501 if (errdes >= 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
502 max = STDERR_FILE_NO; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
503 else if (out >= 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
504 max = STDOUT_FILE_NO; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
505 else if (in >= 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
506 max = STDIN_FILE_NO; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
507 if (in > max) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
508 close (in); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
509 if (out > max) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
510 close (out); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
511 if (errdes > max && errdes != out) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
512 close (errdes); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
513 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
514 /* If we were not given an environment, use the global environment. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
515 if (env == NULL) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
516 env = environ; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
517 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
518 /* Launch the program. If we get EAGAIN (normally out of pid's), try |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
519 again a few times with increasing backoff times. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
520 retries = 0; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
521 while (1) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
522 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
523 typedef const char * const *cc_cp; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
524 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
525 if (flags & PEX_SEARCH) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
526 pid = spawnvpe (_P_NOWAITO, executable, (cc_cp)argv, (cc_cp)env); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
527 else |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
528 pid = spawnve (_P_NOWAITO, executable, (cc_cp)argv, (cc_cp)env); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
529 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
530 if (pid > 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
531 break; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
532 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
533 *err = errno; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
534 *errmsg = "spawn"; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
535 if (errno != EAGAIN || ++retries == 4) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
536 return (pid_t) -1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
537 sleep (1 << retries); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
538 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
539 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
540 /* Success. Restore the parent's file descriptors that we saved above. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
541 if (toclose >= 0 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
542 && restore_fd (toclose, toclose, fl_tc) < 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
543 goto error_dup2; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
544 if (in != STDIN_FILE_NO |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
545 && restore_fd (STDIN_FILE_NO, save_in, fl_in) < 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
546 goto error_dup2; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
547 if (out != STDOUT_FILE_NO |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
548 && restore_fd (STDOUT_FILE_NO, save_out, fl_out) < 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
549 goto error_dup2; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
550 if (errdes != STDERR_FILE_NO |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
551 && restore_fd (STDERR_FILE_NO, save_err, fl_err) < 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
552 goto error_dup2; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
553 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
554 return pid; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
555 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
556 error_dup2: |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
557 *err = errno; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
558 *errmsg = "dup2"; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
559 return (pid_t) -1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
560 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
561 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
562 #else |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
563 /* Implementation of pex->exec_child using standard vfork + exec. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
564 |
0 | 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 { | |
131 | 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_CLOEXEC | |
583 do_pipe = 1; | |
584 #endif | |
585 if (do_pipe) | |
586 { | |
587 #ifdef HAVE_PIPE2 | |
588 if (pipe2 ((int *)pipes, O_CLOEXEC)) | |
589 do_pipe = 0; | |
590 #else | |
591 if (pipe ((int *)pipes)) | |
592 do_pipe = 0; | |
593 else | |
594 { | |
595 if (fcntl (pipes[1], F_SETFD, FD_CLOEXEC) == -1) | |
596 { | |
597 close (pipes[0]); | |
598 close (pipes[1]); | |
599 do_pipe = 0; | |
600 } | |
601 } | |
602 #endif | |
603 } | |
0 | 604 |
605 /* We declare these to be volatile to avoid warnings from gcc about | |
606 them being clobbered by vfork. */ | |
131 | 607 volatile int sleep_interval = 1; |
0 | 608 volatile int retries; |
609 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
610 /* We vfork and then set environ in the child before calling execvp. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
611 This clobbers the parent's environ so we need to restore it. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
612 It would be nice to use one of the exec* functions that takes an |
131 | 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; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
617 |
0 | 618 for (retries = 0; retries < 4; ++retries) |
619 { | |
620 pid = vfork (); | |
621 if (pid >= 0) | |
622 break; | |
623 sleep (sleep_interval); | |
624 sleep_interval *= 2; | |
625 } | |
626 | |
627 switch (pid) | |
628 { | |
629 case -1: | |
131 | 630 if (do_pipe) |
631 { | |
632 close (pipes[0]); | |
633 close (pipes[1]); | |
634 } | |
0 | 635 *err = errno; |
636 *errmsg = VFORK_STRING; | |
637 return (pid_t) -1; | |
638 | |
639 case 0: | |
640 /* Child process. */ | |
131 | 641 { |
642 struct fn_err failed; | |
643 failed.fn = NULL; | |
0 | 644 |
131 | 645 if (do_pipe) |
646 close (pipes[0]); | |
647 if (!failed.fn && in != STDIN_FILE_NO) | |
648 { | |
649 if (dup2 (in, STDIN_FILE_NO) < 0) | |
650 failed.fn = "dup2", failed.err = errno; | |
651 else if (close (in) < 0) | |
652 failed.fn = "close", failed.err = errno; | |
653 } | |
654 if (!failed.fn && out != STDOUT_FILE_NO) | |
655 { | |
656 if (dup2 (out, STDOUT_FILE_NO) < 0) | |
657 failed.fn = "dup2", failed.err = errno; | |
658 else if (close (out) < 0) | |
659 failed.fn = "close", failed.err = errno; | |
660 } | |
661 if (!failed.fn && errdes != STDERR_FILE_NO) | |
662 { | |
663 if (dup2 (errdes, STDERR_FILE_NO) < 0) | |
664 failed.fn = "dup2", failed.err = errno; | |
665 else if (close (errdes) < 0) | |
666 failed.fn = "close", failed.err = errno; | |
667 } | |
668 if (!failed.fn && toclose >= 0) | |
669 { | |
670 if (close (toclose) < 0) | |
671 failed.fn = "close", failed.err = errno; | |
672 } | |
673 if (!failed.fn && (flags & PEX_STDERR_TO_STDOUT) != 0) | |
674 { | |
675 if (dup2 (STDOUT_FILE_NO, STDERR_FILE_NO) < 0) | |
676 failed.fn = "dup2", failed.err = errno; | |
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_SEARCH) != 0) | |
686 { | |
687 execvp (executable, to_ptr32 (argv)); | |
688 failed.fn = "execvp", failed.err = errno; | |
689 } | |
690 else | |
691 { | |
692 execv (executable, to_ptr32 (argv)); | |
693 failed.fn = "execv", failed.err = errno; | |
694 } | |
695 } | |
0 | 696 |
131 | 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; | |
0 | 700 |
131 | 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_NO, 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 } | |
0 | 721 /* NOTREACHED */ |
722 return (pid_t) -1; | |
723 | |
724 default: | |
725 /* Parent process. */ | |
131 | 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; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
733 |
131 | 734 struct fn_err failed; |
735 failed.fn = NULL; | |
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; | |
742 close (pipes[0]); | |
743 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
744 |
131 | 745 if (!failed.fn && in != STDIN_FILE_NO) |
0 | 746 if (close (in) < 0) |
131 | 747 failed.fn = "close", failed.err = errno; |
748 if (!failed.fn && out != STDOUT_FILE_NO) | |
0 | 749 if (close (out) < 0) |
131 | 750 failed.fn = "close", failed.err = errno; |
751 if (!failed.fn && errdes != STDERR_FILE_NO) | |
0 | 752 if (close (errdes) < 0) |
131 | 753 failed.fn = "close", failed.err = errno; |
0 | 754 |
131 | 755 if (failed.fn) |
756 { | |
757 *err = failed.err; | |
758 *errmsg = failed.fn; | |
759 return (pid_t) -1; | |
760 } | |
761 } | |
0 | 762 return pid; |
763 } | |
764 } | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
765 #endif /* SPAWN */ |
0 | 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, SIGTERM); | |
778 | |
779 if (pex_wait (obj, pid, status, time) < 0) | |
780 { | |
781 *err = errno; | |
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, int *p, | |
793 int binary 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, int fd, | |
802 int binary ATTRIBUTE_UNUSED) | |
803 { | |
804 return fdopen (fd, "r"); | |
805 } | |
806 | |
807 static FILE * | |
808 pex_unix_fdopenw (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd, | |
809 int binary ATTRIBUTE_UNUSED) | |
810 { | |
811 if (fcntl (fd, F_SETFD, FD_CLOEXEC) < 0) | |
812 return NULL; | |
813 return fdopen (fd, "w"); | |
814 } | |
815 | |
816 static void | |
817 pex_unix_cleanup (struct pex_obj *obj ATTRIBUTE_UNUSED) | |
818 { | |
819 #if !defined (HAVE_WAIT4) && !defined (HAVE_WAITPID) | |
820 while (obj->sysdep != NULL) | |
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 } |