xref: /openbsd-src/gnu/lib/libiberty/src/pexecute.c (revision 91f110e064cd7c194e59e019b83bb7496c1c84d4)
1 /* 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) */
793