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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [libiberty/] [pexecute.c] - Blame information for rev 1774

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

Line No. Rev Author Line
1 578 markom
/* Utilities to execute a program in a subprocess (possibly linked by pipes
2
   with other subprocesses), and wait for it.
3
   Copyright (C) 1996-2000 Free Software Foundation, Inc.
4
 
5
This file is part of the libiberty library.
6
Libiberty is free software; you can redistribute it and/or
7
modify it under the terms of the GNU Library General Public
8
License as published by the Free Software Foundation; either
9
version 2 of the License, or (at your option) any later version.
10
 
11
Libiberty is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
Library General Public License for more details.
15
 
16
You should have received a copy of the GNU Library General Public
17
License along with libiberty; see the file COPYING.LIB.  If not,
18
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19
Boston, MA 02111-1307, USA.  */
20
 
21
/* This file exports two functions: pexecute and pwait.  */
22
 
23
/* This file lives in at least two places: libiberty and gcc.
24
   Don't change one without the other.  */
25
 
26
#ifdef HAVE_CONFIG_H
27
#include "config.h"
28
#endif
29
 
30
#include <stdio.h>
31
#include <errno.h>
32
#ifdef NEED_DECLARATION_ERRNO
33
extern int errno;
34
#endif
35
#ifdef HAVE_STRING_H
36
#include <string.h>
37
#endif
38
#ifdef HAVE_UNISTD_H
39
#include <unistd.h>
40
#endif
41
#ifdef HAVE_STDLIB_H
42
#include <stdlib.h>
43
#endif
44
#ifdef HAVE_SYS_WAIT_H
45
#include <sys/wait.h>
46
#endif
47
 
48
#include "libiberty.h"
49
#include "safe-ctype.h"
50
 
51
/* stdin file number.  */
52
#define STDIN_FILE_NO 0
53
 
54
/* stdout file number.  */
55
#define STDOUT_FILE_NO 1
56
 
57
/* value of `pipe': port index for reading.  */
58
#define READ_PORT 0
59
 
60
/* value of `pipe': port index for writing.  */
61
#define WRITE_PORT 1
62
 
63
static char *install_error_msg = "installation problem, cannot exec `%s'";
64
 
65
/* pexecute: execute a program.
66
 
67
   PROGRAM and ARGV are the arguments to execv/execvp.
68
 
69
   THIS_PNAME is name of the calling program (i.e. argv[0]).
70
 
71
   TEMP_BASE is the path name, sans suffix, of a temporary file to use
72
   if needed.  This is currently only needed for MSDOS ports that don't use
73
   GO32 (do any still exist?).  Ports that don't need it can pass NULL.
74
 
75
   (FLAGS & PEXECUTE_SEARCH) is non-zero if $PATH should be searched
76
   (??? It's not clear that GCC passes this flag correctly).
77
   (FLAGS & PEXECUTE_FIRST) is nonzero for the first process in chain.
78
   (FLAGS & PEXECUTE_FIRST) is nonzero for the last process in chain.
79
   FIRST_LAST could be simplified to only mark the last of a chain of processes
80
   but that requires the caller to always mark the last one (and not give up
81
   early if some error occurs).  It's more robust to require the caller to
82
   mark both ends of the chain.
83
 
84
   The result is the pid on systems like Unix where we fork/exec and on systems
85
   like WIN32 and OS2 where we use spawn.  It is up to the caller to wait for
86
   the child.
87
 
88
   The result is the WEXITSTATUS on systems like MSDOS where we spawn and wait
89
   for the child here.
90
 
91
   Upon failure, ERRMSG_FMT and ERRMSG_ARG are set to the text of the error
92
   message with an optional argument (if not needed, ERRMSG_ARG is set to
93
   NULL), and -1 is returned.  `errno' is available to the caller to use.
94
 
95
   pwait: cover function for wait.
96
 
97
   PID is the process id of the task to wait for.
98
   STATUS is the `status' argument to wait.
99
   FLAGS is currently unused (allows future enhancement without breaking
100
   upward compatibility).  Pass 0 for now.
101
 
102
   The result is the pid of the child reaped,
103
   or -1 for failure (errno says why).
104
 
105
   On systems that don't support waiting for a particular child, PID is
106
   ignored.  On systems like MSDOS that don't really multitask pwait
107
   is just a mechanism to provide a consistent interface for the caller.
108
 
109
   pfinish: finish generation of script
110
 
111
   pfinish is necessary for systems like MPW where a script is generated that
112
   runs the requested programs.
113
*/
114
 
115
#ifdef __MSDOS__
116
 
117
/* MSDOS doesn't multitask, but for the sake of a consistent interface
118
   the code behaves like it does.  pexecute runs the program, tucks the
119
   exit code away, and returns a "pid".  pwait must be called to fetch the
120
   exit code.  */
121
 
122
#include <process.h>
123
 
124
/* For communicating information from pexecute to pwait.  */
125
static int last_pid = 0;
126
static int last_status = 0;
127
static int last_reaped = 0;
128
 
129
int
130
pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
131
     const char *program;
132
     char * const *argv;
133
     const char *this_pname;
134
     const char *temp_base;
135
     char **errmsg_fmt, **errmsg_arg;
136
     int flags;
137
{
138
  int rc;
139
 
140
  last_pid++;
141
  if (last_pid < 0)
142
    last_pid = 1;
143
 
144
  if ((flags & PEXECUTE_ONE) != PEXECUTE_ONE)
145
    abort ();
146
 
147
#ifdef __DJGPP__
148
  /* ??? What are the possible return values from spawnv?  */
149
  rc = (flags & PEXECUTE_SEARCH ? spawnvp : spawnv) (P_WAIT, program, argv);
150
#else
151
  char *scmd, *rf;
152
  FILE *argfile;
153
  int i, el = flags & PEXECUTE_SEARCH ? 4 : 0;
154
 
155
  if (temp_base == 0)
156
    temp_base = choose_temp_base ();
157
  scmd = (char *) xmalloc (strlen (program) + strlen (temp_base) + 6 + el);
158
  rf = scmd + strlen(program) + 2 + el;
159
  sprintf (scmd, "%s%s @%s.gp", program,
160
           (flags & PEXECUTE_SEARCH ? ".exe" : ""), temp_base);
161
  argfile = fopen (rf, "w");
162
  if (argfile == 0)
163
    {
164
      int errno_save = errno;
165
      free (scmd);
166
      errno = errno_save;
167
      *errmsg_fmt = "cannot open `%s.gp'";
168
      *errmsg_arg = temp_base;
169
      return -1;
170
    }
171
 
172
  for (i=1; argv[i]; i++)
173
    {
174
      char *cp;
175
      for (cp = argv[i]; *cp; cp++)
176
        {
177
          if (*cp == '"' || *cp == '\'' || *cp == '\\' || ISSPACE (*cp))
178
            fputc ('\\', argfile);
179
          fputc (*cp, argfile);
180
        }
181
      fputc ('\n', argfile);
182
    }
183
  fclose (argfile);
184
 
185
  rc = system (scmd);
186
 
187
  {
188
    int errno_save = errno;
189
    remove (rf);
190
    free (scmd);
191
    errno = errno_save;
192
  }
193
#endif
194
 
195
  if (rc == -1)
196
    {
197
      *errmsg_fmt = install_error_msg;
198
      *errmsg_arg = (char *)program;
199
      return -1;
200
    }
201
 
202
  /* Tuck the status away for pwait, and return a "pid".  */
203
  last_status = rc << 8;
204
  return last_pid;
205
}
206
 
207
/* Use ECHILD if available, otherwise use EINVAL.  */
208
#ifdef ECHILD
209
#define PWAIT_ERROR ECHILD
210
#else
211
#define PWAIT_ERROR EINVAL
212
#endif
213
 
214
int
215
pwait (pid, status, flags)
216
     int pid;
217
     int *status;
218
     int flags;
219
{
220
  /* On MSDOS each pexecute must be followed by it's associated pwait.  */
221
  if (pid != last_pid
222
      /* Called twice for the same child?  */
223
      || pid == last_reaped)
224
    {
225
      errno = PWAIT_ERROR;
226
      return -1;
227
    }
228
  /* ??? Here's an opportunity to canonicalize the values in STATUS.
229
     Needed?  */
230
#ifdef __DJGPP__
231
  *status = (last_status >> 8);
232
#else
233
  *status = last_status;
234
#endif
235
  last_reaped = last_pid;
236
  return last_pid;
237
}
238
 
239
#endif /* MSDOS */
240
 
241
#if defined (_WIN32) && ! defined (_UWIN)
242
 
243
#include <process.h>
244
 
245
#ifdef __CYGWIN__
246
 
247
#define fix_argv(argvec) (argvec)
248
 
249
extern int _spawnv ();
250
extern int _spawnvp ();
251
 
252
#else /* ! __CYGWIN__ */
253
 
254
/* This is a kludge to get around the Microsoft C spawn functions' propensity
255
   to remove the outermost set of double quotes from all arguments.  */
256
 
257
const char * const *
258
fix_argv (argvec)
259
     char **argvec;
260
{
261
  int i;
262
 
263
  for (i = 1; argvec[i] != 0; i++)
264
    {
265
      int len, j;
266
      char *temp, *newtemp;
267
 
268
      temp = argvec[i];
269
      len = strlen (temp);
270
      for (j = 0; j < len; j++)
271
        {
272
          if (temp[j] == '"')
273
            {
274
              newtemp = xmalloc (len + 2);
275
              strncpy (newtemp, temp, j);
276
              newtemp [j] = '\\';
277
              strncpy (&newtemp [j+1], &temp [j], len-j);
278
              newtemp [len+1] = 0;
279
              temp = newtemp;
280
              len++;
281
              j++;
282
            }
283
        }
284
 
285
        argvec[i] = temp;
286
      }
287
 
288
  for (i = 0; argvec[i] != 0; i++)
289
    {
290
      if (strpbrk (argvec[i], " \t"))
291
        {
292
          int len, trailing_backslash;
293
          char *temp;
294
 
295
          len = strlen (argvec[i]);
296
          trailing_backslash = 0;
297
 
298
          /* There is an added complication when an arg with embedded white
299
             space ends in a backslash (such as in the case of -iprefix arg
300
             passed to cpp). The resulting quoted strings gets misinterpreted
301
             by the command interpreter -- it thinks that the ending quote
302
             is escaped by the trailing backslash and things get confused.
303
             We handle this case by escaping the trailing backslash, provided
304
             it was not escaped in the first place.  */
305
          if (len > 1
306
              && argvec[i][len-1] == '\\'
307
              && argvec[i][len-2] != '\\')
308
            {
309
              trailing_backslash = 1;
310
              ++len;                    /* to escape the final backslash. */
311
            }
312
 
313
          len += 2;                     /* and for the enclosing quotes. */
314
 
315
          temp = xmalloc (len + 1);
316
          temp[0] = '"';
317
          strcpy (temp + 1, argvec[i]);
318
          if (trailing_backslash)
319
            temp[len-2] = '\\';
320
          temp[len-1] = '"';
321
          temp[len] = '\0';
322
 
323
          argvec[i] = temp;
324
        }
325
    }
326
 
327
  return (const char * const *) argvec;
328
}
329
#endif /* __CYGWIN__ */
330
 
331
#include <io.h>
332
#include <fcntl.h>
333
#include <signal.h>
334
 
335
/* mingw32 headers may not define the following.  */
336
 
337
#ifndef _P_WAIT
338
#  define _P_WAIT       0
339
#  define _P_NOWAIT     1
340
#  define _P_OVERLAY    2
341
#  define _P_NOWAITO    3
342
#  define _P_DETACH     4
343
 
344
#  define WAIT_CHILD    0
345
#  define WAIT_GRANDCHILD       1
346
#endif
347
 
348
/* Win32 supports pipes */
349
int
350
pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
351
     const char *program;
352
     char * const *argv;
353
     const char *this_pname;
354
     const char *temp_base;
355
     char **errmsg_fmt, **errmsg_arg;
356
     int flags;
357
{
358
  int pid;
359
  int pdes[2], org_stdin, org_stdout;
360
  int input_desc, output_desc;
361
  int retries, sleep_interval;
362
 
363
  /* Pipe waiting from last process, to be used as input for the next one.
364
     Value is STDIN_FILE_NO if no pipe is waiting
365
     (i.e. the next command is the first of a group).  */
366
  static int last_pipe_input;
367
 
368
  /* If this is the first process, initialize.  */
369
  if (flags & PEXECUTE_FIRST)
370
    last_pipe_input = STDIN_FILE_NO;
371
 
372
  input_desc = last_pipe_input;
373
 
374
  /* If this isn't the last process, make a pipe for its output,
375
     and record it as waiting to be the input to the next process.  */
376
  if (! (flags & PEXECUTE_LAST))
377
    {
378
      if (_pipe (pdes, 256, O_BINARY) < 0)
379
        {
380
          *errmsg_fmt = "pipe";
381
          *errmsg_arg = NULL;
382
          return -1;
383
        }
384
      output_desc = pdes[WRITE_PORT];
385
      last_pipe_input = pdes[READ_PORT];
386
    }
387
  else
388
    {
389
      /* Last process.  */
390
      output_desc = STDOUT_FILE_NO;
391
      last_pipe_input = STDIN_FILE_NO;
392
    }
393
 
394
  if (input_desc != STDIN_FILE_NO)
395
    {
396
      org_stdin = dup (STDIN_FILE_NO);
397
      dup2 (input_desc, STDIN_FILE_NO);
398
      close (input_desc);
399
    }
400
 
401
  if (output_desc != STDOUT_FILE_NO)
402
    {
403
      org_stdout = dup (STDOUT_FILE_NO);
404
      dup2 (output_desc, STDOUT_FILE_NO);
405
      close (output_desc);
406
    }
407
 
408
  pid = (flags & PEXECUTE_SEARCH ? _spawnvp : _spawnv)
409
    (_P_NOWAIT, program, fix_argv(argv));
410
 
411
  if (input_desc != STDIN_FILE_NO)
412
    {
413
      dup2 (org_stdin, STDIN_FILE_NO);
414
      close (org_stdin);
415
    }
416
 
417
  if (output_desc != STDOUT_FILE_NO)
418
    {
419
      dup2 (org_stdout, STDOUT_FILE_NO);
420
      close (org_stdout);
421
    }
422
 
423
  if (pid == -1)
424
    {
425
      *errmsg_fmt = install_error_msg;
426
      *errmsg_arg = program;
427
      return -1;
428
    }
429
 
430
  return pid;
431
}
432
 
433
/* MS CRTDLL doesn't return enough information in status to decide if the
434
   child exited due to a signal or not, rather it simply returns an
435
   integer with the exit code of the child; eg., if the child exited with
436
   an abort() call and didn't have a handler for SIGABRT, it simply returns
437
   with status = 3. We fix the status code to conform to the usual WIF*
438
   macros. Note that WIFSIGNALED will never be true under CRTDLL. */
439
 
440
int
441
pwait (pid, status, flags)
442
     int pid;
443
     int *status;
444
     int flags;
445
{
446
#ifdef __CYGWIN__
447
  return wait (status);
448
#else
449
  int termstat;
450
 
451
  pid = _cwait (&termstat, pid, WAIT_CHILD);
452
 
453
  /* ??? Here's an opportunity to canonicalize the values in STATUS.
454
     Needed?  */
455
 
456
  /* cwait returns the child process exit code in termstat.
457
     A value of 3 indicates that the child caught a signal, but not
458
     which one.  Since only SIGABRT, SIGFPE and SIGINT do anything, we
459
     report SIGABRT.  */
460
  if (termstat == 3)
461
    *status = SIGABRT;
462
  else
463
    *status = (((termstat) & 0xff) << 8);
464
 
465
  return pid;
466
#endif /* __CYGWIN__ */
467
}
468
 
469
#endif /* _WIN32 && ! _UWIN */
470
 
471
#ifdef OS2
472
 
473
/* ??? Does OS2 have process.h?  */
474
extern int spawnv ();
475
extern int spawnvp ();
476
 
477
int
478
pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
479
     const char *program;
480
     char * const *argv;
481
     const char *this_pname;
482
     const char *temp_base;
483
     char **errmsg_fmt, **errmsg_arg;
484
     int flags;
485
{
486
  int pid;
487
 
488
  if ((flags & PEXECUTE_ONE) != PEXECUTE_ONE)
489
    abort ();
490
  /* ??? Presumably 1 == _P_NOWAIT.  */
491
  pid = (flags & PEXECUTE_SEARCH ? spawnvp : spawnv) (1, program, argv);
492
  if (pid == -1)
493
    {
494
      *errmsg_fmt = install_error_msg;
495
      *errmsg_arg = program;
496
      return -1;
497
    }
498
  return pid;
499
}
500
 
501
int
502
pwait (pid, status, flags)
503
     int pid;
504
     int *status;
505
     int flags;
506
{
507
  /* ??? Here's an opportunity to canonicalize the values in STATUS.
508
     Needed?  */
509
  int pid = wait (status);
510
  return pid;
511
}
512
 
513
#endif /* OS2 */
514
 
515
#ifdef MPW
516
 
517
/* MPW pexecute doesn't actually run anything; instead, it writes out
518
   script commands that, when run, will do the actual executing.
519
 
520
   For example, in GCC's case, GCC will write out several script commands:
521
 
522
   cpp ...
523
   cc1 ...
524
   as ...
525
   ld ...
526
 
527
   and then exit.  None of the above programs will have run yet.  The task
528
   that called GCC will then execute the script and cause cpp,etc. to run.
529
   The caller must invoke pfinish before calling exit.  This adds
530
   the finishing touches to the generated script.  */
531
 
532
static int first_time = 1;
533
 
534
int
535
pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
536
     const char *program;
537
     char * const *argv;
538
     const char *this_pname;
539
     const char *temp_base;
540
     char **errmsg_fmt, **errmsg_arg;
541
     int flags;
542
{
543
  char tmpprogram[255];
544
  char *cp, *tmpname;
545
  int i;
546
 
547
  mpwify_filename (program, tmpprogram);
548
  if (first_time)
549
    {
550
      printf ("Set Failed 0\n");
551
      first_time = 0;
552
    }
553
 
554
  fputs ("If {Failed} == 0\n", stdout);
555
  /* If being verbose, output a copy of the command.  It should be
556
     accurate enough and escaped enough to be "clickable".  */
557
  if (flags & PEXECUTE_VERBOSE)
558
    {
559
      fputs ("\tEcho ", stdout);
560
      fputc ('\'', stdout);
561
      fputs (tmpprogram, stdout);
562
      fputc ('\'', stdout);
563
      fputc (' ', stdout);
564
      for (i=1; argv[i]; i++)
565
        {
566
          fputc ('\'', stdout);
567
          /* See if we have an argument that needs fixing.  */
568
          if (strchr(argv[i], '/'))
569
            {
570
              tmpname = (char *) xmalloc (256);
571
              mpwify_filename (argv[i], tmpname);
572
              argv[i] = tmpname;
573
            }
574
          for (cp = argv[i]; *cp; cp++)
575
            {
576
              /* Write an Option-d escape char in front of special chars.  */
577
              if (strchr("'+", *cp))
578
                fputc ('\266', stdout);
579
              fputc (*cp, stdout);
580
            }
581
          fputc ('\'', stdout);
582
          fputc (' ', stdout);
583
        }
584
      fputs ("\n", stdout);
585
    }
586
  fputs ("\t", stdout);
587
  fputs (tmpprogram, stdout);
588
  fputc (' ', stdout);
589
 
590
  for (i=1; argv[i]; i++)
591
    {
592
      /* See if we have an argument that needs fixing.  */
593
      if (strchr(argv[i], '/'))
594
        {
595
          tmpname = (char *) xmalloc (256);
596
          mpwify_filename (argv[i], tmpname);
597
          argv[i] = tmpname;
598
        }
599
      if (strchr (argv[i], ' '))
600
        fputc ('\'', stdout);
601
      for (cp = argv[i]; *cp; cp++)
602
        {
603
          /* Write an Option-d escape char in front of special chars.  */
604
          if (strchr("'+", *cp))
605
            fputc ('\266', stdout);
606
          fputc (*cp, stdout);
607
        }
608
      if (strchr (argv[i], ' '))
609
        fputc ('\'', stdout);
610
      fputc (' ', stdout);
611
    }
612
 
613
  fputs ("\n", stdout);
614
 
615
  /* Output commands that arrange to clean up and exit if a failure occurs.
616
     We have to be careful to collect the status from the program that was
617
     run, rather than some other script command.  Also, we don't exit
618
     immediately, since necessary cleanups are at the end of the script.  */
619
  fputs ("\tSet TmpStatus {Status}\n", stdout);
620
  fputs ("\tIf {TmpStatus} != 0\n", stdout);
621
  fputs ("\t\tSet Failed {TmpStatus}\n", stdout);
622
  fputs ("\tEnd\n", stdout);
623
  fputs ("End\n", stdout);
624
 
625
  /* We're just composing a script, can't fail here.  */
626
  return 0;
627
}
628
 
629
int
630
pwait (pid, status, flags)
631
     int pid;
632
     int *status;
633
     int flags;
634
{
635
  *status = 0;
636
  return 0;
637
}
638
 
639
/* Write out commands that will exit with the correct error code
640
   if something in the script failed.  */
641
 
642
void
643
pfinish ()
644
{
645
  printf ("\tExit \"{Failed}\"\n");
646
}
647
 
648
#endif /* MPW */
649
 
650
/* include for Unix-like environments but not for Dos-like environments */
651
#if ! defined (__MSDOS__) && ! defined (OS2) && ! defined (MPW) \
652
    && ! (defined (_WIN32) && ! defined (_UWIN))
653
 
654
extern int execv ();
655
extern int execvp ();
656
 
657
int
658
pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
659
     const char *program;
660
     char * const *argv;
661
     const char *this_pname;
662
     const char *temp_base ATTRIBUTE_UNUSED;
663
     char **errmsg_fmt, **errmsg_arg;
664
     int flags;
665
{
666
  int (*func)() = (flags & PEXECUTE_SEARCH ? execvp : execv);
667
  int pid;
668
  int pdes[2];
669
  int input_desc, output_desc;
670
  int retries, sleep_interval;
671
  /* Pipe waiting from last process, to be used as input for the next one.
672
     Value is STDIN_FILE_NO if no pipe is waiting
673
     (i.e. the next command is the first of a group).  */
674
  static int last_pipe_input;
675
 
676
  /* If this is the first process, initialize.  */
677
  if (flags & PEXECUTE_FIRST)
678
    last_pipe_input = STDIN_FILE_NO;
679
 
680
  input_desc = last_pipe_input;
681
 
682
  /* If this isn't the last process, make a pipe for its output,
683
     and record it as waiting to be the input to the next process.  */
684
  if (! (flags & PEXECUTE_LAST))
685
    {
686
      if (pipe (pdes) < 0)
687
        {
688
          *errmsg_fmt = "pipe";
689
          *errmsg_arg = NULL;
690
          return -1;
691
        }
692
      output_desc = pdes[WRITE_PORT];
693
      last_pipe_input = pdes[READ_PORT];
694
    }
695
  else
696
    {
697
      /* Last process.  */
698
      output_desc = STDOUT_FILE_NO;
699
      last_pipe_input = STDIN_FILE_NO;
700
    }
701
 
702
  /* Fork a subprocess; wait and retry if it fails.  */
703
  sleep_interval = 1;
704
  pid = -1;
705
  for (retries = 0; retries < 4; retries++)
706
    {
707
      pid = fork ();
708
      if (pid >= 0)
709
        break;
710
      sleep (sleep_interval);
711
      sleep_interval *= 2;
712
    }
713
 
714
  switch (pid)
715
    {
716
    case -1:
717
      *errmsg_fmt = "fork";
718
      *errmsg_arg = NULL;
719
      return -1;
720
 
721
    case 0: /* child */
722
      /* Move the input and output pipes into place, if necessary.  */
723
      if (input_desc != STDIN_FILE_NO)
724
        {
725
          close (STDIN_FILE_NO);
726
          dup (input_desc);
727
          close (input_desc);
728
        }
729
      if (output_desc != STDOUT_FILE_NO)
730
        {
731
          close (STDOUT_FILE_NO);
732
          dup (output_desc);
733
          close (output_desc);
734
        }
735
 
736
      /* Close the parent's descs that aren't wanted here.  */
737
      if (last_pipe_input != STDIN_FILE_NO)
738
        close (last_pipe_input);
739
 
740
      /* Exec the program.  */
741
      (*func) (program, argv);
742
 
743
      fprintf (stderr, "%s: ", this_pname);
744
      fprintf (stderr, install_error_msg, program);
745
      fprintf (stderr, ": %s\n", xstrerror (errno));
746
      exit (-1);
747
      /* NOTREACHED */
748
      return 0;
749
 
750
    default:
751
      /* In the parent, after forking.
752
         Close the descriptors that we made for this child.  */
753
      if (input_desc != STDIN_FILE_NO)
754
        close (input_desc);
755
      if (output_desc != STDOUT_FILE_NO)
756
        close (output_desc);
757
 
758
      /* Return child's process number.  */
759
      return pid;
760
    }
761
}
762
 
763
int
764
pwait (pid, status, flags)
765
     int pid;
766
     int *status;
767
     int flags ATTRIBUTE_UNUSED;
768
{
769
  /* ??? Here's an opportunity to canonicalize the values in STATUS.
770
     Needed?  */
771
#ifdef VMS
772
  pid = waitpid (-1, status, 0);
773
#else
774
  pid = wait (status);
775
#endif
776
  return pid;
777
}
778
 
779
#endif /* ! __MSDOS__ && ! OS2 && ! MPW && ! (_WIN32 && ! _UWIN) */

powered by: WebSVN 2.1.0

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