OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [libiberty/] [pex-unix.c] - Blame information for rev 53

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.