Mercurial > hg > CbC > CbC_gcc
annotate libiberty/pex-unix.c @ 108:7ad14f446135
add CbC-example/rectypeTest/
author | Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Thu, 14 Jun 2012 20:30:24 +0900 |
parents | f6334be47118 |
children | 04ced10e8804 |
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). | |
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
|
4 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2009, |
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
|
5 2010 Free Software Foundation, Inc. |
0 | 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 | |
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 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
88 for (argc=0; ptr64[argc]; argc++); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
89 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
90 /* 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
|
91 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
|
92 (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
|
93 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
94 for (argc=0; ptr64[argc]; argc++) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
95 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
|
96 |
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) 0; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
98 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
|
99 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
100 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
101 #else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
102 #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
|
103 #endif |
0 | 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 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
373 int retval = 0; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
374 #define writeerr(s) retval |= (write (STDERR_FILE_NO, s, strlen (s)) < 0) |
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"); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
383 #undef writeerr |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
384 /* Exit with -2 if the error output failed, too. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
385 _exit (retval == 0 ? -1 : -2); |
0 | 386 } |
387 | |
388 /* Execute a child. */ | |
389 | |
390 extern char **environ; | |
391 | |
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
|
392 #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
|
393 /* 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
|
394 |
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 /* 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
|
396 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
|
397 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
|
398 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
|
399 |
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 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
|
401 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
|
402 { |
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 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
|
404 |
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 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
|
406 |
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 /* 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
|
408 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
|
409 { |
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 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
|
411 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
|
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 } |
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 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
|
415 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
|
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 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
|
418 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
|
419 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
|
420 } |
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 /* 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
|
422 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
|
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 #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
|
425 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
|
426 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
|
427 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
|
428 #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
|
429 /* 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
|
430 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
|
431 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
|
432 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
|
433 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
|
434 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
|
435 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
|
436 #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
|
437 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
|
438 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
|
439 } |
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 |
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 *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
|
442 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
|
443 *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
|
444 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
|
445 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
|
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 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
|
448 } |
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 |
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 /* 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
|
451 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
|
452 |
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 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
|
454 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
|
455 { |
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 /* 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
|
457 "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
|
458 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
|
459 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
|
460 |
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 /* 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
|
462 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
|
463 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
|
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 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
|
466 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
|
467 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
|
468 } |
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 |
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 /* 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
|
471 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
|
472 #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
|
473 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
|
474 { |
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 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
|
476 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
|
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 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
|
479 #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
|
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 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
|
482 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
|
483 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
|
484 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
|
485 } |
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 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
|
487 } |
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 |
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 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
|
490 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
|
491 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
|
492 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
|
493 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
|
494 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
|
495 { |
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 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
|
497 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
|
498 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
|
499 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
|
500 |
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 (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
|
502 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
|
503 |
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 /* 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
|
505 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
|
506 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
|
507 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
|
508 && 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
|
509 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
|
510 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
|
511 && 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
|
512 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
|
513 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
|
514 && 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
|
515 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
|
516 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
|
517 && 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
|
518 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
|
519 |
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 /* 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
|
521 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
|
522 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
|
523 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
|
524 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
|
525 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
|
526 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
|
527 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
|
528 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
|
529 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
|
530 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
|
531 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
|
532 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
|
533 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
|
534 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
|
535 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
|
536 |
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 /* 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
|
538 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
|
539 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
|
540 |
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 /* 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
|
542 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
|
543 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
|
544 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
|
545 { |
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 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
|
547 |
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 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
|
549 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
|
550 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
|
551 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
|
552 |
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 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
|
554 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
|
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 *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
|
557 *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
|
558 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
|
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 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
|
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 |
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 /* 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
|
564 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
|
565 && 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
|
566 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
|
567 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
|
568 && 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
|
569 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
|
570 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
|
571 && 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
|
572 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
|
573 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
|
574 && 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
|
575 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
|
576 |
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
|
577 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
|
578 |
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
|
579 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
|
580 *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
|
581 *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
|
582 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
|
583 } |
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
|
584 |
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
|
585 #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
|
586 /* 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
|
587 |
0 | 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 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
601 /* 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
|
602 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
|
603 It would be nice to use one of the exec* functions that takes an |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
604 environment as a parameter, but that may have portability issues. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
605 char **save_environ = environ; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
606 |
0 | 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) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
660 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
661 /* NOTE: In a standard vfork implementation this clobbers the |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
662 parent's copy of environ "too" (in reality there's only one copy). |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
663 This is ok as we restore it below. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
664 environ = (char**) env; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
665 } |
0 | 666 |
667 if ((flags & PEX_SEARCH) != 0) | |
668 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
669 execvp (executable, to_ptr32 (argv)); |
0 | 670 pex_child_error (obj, executable, "execvp", errno); |
671 } | |
672 else | |
673 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
674 execv (executable, to_ptr32 (argv)); |
0 | 675 pex_child_error (obj, executable, "execv", errno); |
676 } | |
677 | |
678 /* NOTREACHED */ | |
679 return (pid_t) -1; | |
680 | |
681 default: | |
682 /* Parent process. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
683 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
684 /* Restore environ. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
685 Note that the parent either doesn't run until the child execs/exits |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
686 (standard vfork behaviour), or if it does run then vfork is behaving |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
687 more like fork. In either case we needn't worry about clobbering |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
688 the child's copy of environ. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
689 environ = save_environ; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
690 |
0 | 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 } | |
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
|
722 #endif /* SPAWN */ |
0 | 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 } |