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