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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [libiberty/] [pexecute.c] - Blame information for rev 1767

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

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