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