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