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