Coverage Report

Created: 2025-06-24 06:45

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