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