1 /* Utilities to execute a program in a subprocess (possibly linked by pipes 2 with other subprocesses), and wait for it. Generic Unix version 3 (also used for UWIN and VMS). 4 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003 5 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., 59 Temple Place - Suite 330, 21 Boston, MA 02111-1307, USA. */ 22 23 #include "pex-common.h" 24 25 #include <stdio.h> 26 #include <errno.h> 27 #ifdef NEED_DECLARATION_ERRNO 28 extern int errno; 29 #endif 30 #ifdef HAVE_STRING_H 31 #include <string.h> 32 #endif 33 #ifdef HAVE_UNISTD_H 34 #include <unistd.h> 35 #endif 36 #ifdef HAVE_STDLIB_H 37 #include <stdlib.h> 38 #endif 39 #ifdef HAVE_SYS_WAIT_H 40 #include <sys/wait.h> 41 #endif 42 43 #ifndef HAVE_WAITPID 44 #define waitpid(pid, status, flags) wait(status) 45 #endif 46 47 extern int execv (); 48 extern int execvp (); 49 50 int 51 pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags) 52 const char *program; 53 char * const *argv; 54 const char *this_pname; 55 const char *temp_base ATTRIBUTE_UNUSED; 56 char **errmsg_fmt, **errmsg_arg; 57 int flags; 58 { 59 int (*func)() = (flags & PEXECUTE_SEARCH ? execvp : execv); 60 int pid; 61 int pdes[2]; 62 int input_desc, output_desc; 63 int retries, sleep_interval; 64 /* Pipe waiting from last process, to be used as input for the next one. 65 Value is STDIN_FILE_NO if no pipe is waiting 66 (i.e. the next command is the first of a group). */ 67 static int last_pipe_input; 68 69 /* If this is the first process, initialize. */ 70 if (flags & PEXECUTE_FIRST) 71 last_pipe_input = STDIN_FILE_NO; 72 73 input_desc = last_pipe_input; 74 75 /* If this isn't the last process, make a pipe for its output, 76 and record it as waiting to be the input to the next process. */ 77 if (! (flags & PEXECUTE_LAST)) 78 { 79 if (pipe (pdes) < 0) 80 { 81 *errmsg_fmt = "pipe"; 82 *errmsg_arg = NULL; 83 return -1; 84 } 85 output_desc = pdes[WRITE_PORT]; 86 last_pipe_input = pdes[READ_PORT]; 87 } 88 else 89 { 90 /* Last process. */ 91 output_desc = STDOUT_FILE_NO; 92 last_pipe_input = STDIN_FILE_NO; 93 } 94 95 /* Fork a subprocess; wait and retry if it fails. */ 96 sleep_interval = 1; 97 pid = -1; 98 for (retries = 0; retries < 4; retries++) 99 { 100 pid = fork (); 101 if (pid >= 0) 102 break; 103 sleep (sleep_interval); 104 sleep_interval *= 2; 105 } 106 107 switch (pid) 108 { 109 case -1: 110 *errmsg_fmt = "fork"; 111 *errmsg_arg = NULL; 112 return -1; 113 114 case 0: /* child */ 115 /* Move the input and output pipes into place, if necessary. */ 116 if (input_desc != STDIN_FILE_NO) 117 { 118 close (STDIN_FILE_NO); 119 dup (input_desc); 120 close (input_desc); 121 } 122 if (output_desc != STDOUT_FILE_NO) 123 { 124 close (STDOUT_FILE_NO); 125 dup (output_desc); 126 close (output_desc); 127 } 128 129 /* Close the parent's descs that aren't wanted here. */ 130 if (last_pipe_input != STDIN_FILE_NO) 131 close (last_pipe_input); 132 133 /* Exec the program. */ 134 (*func) (program, argv); 135 136 fprintf (stderr, "%s: ", this_pname); 137 fprintf (stderr, install_error_msg, program); 138 fprintf (stderr, ": %s\n", xstrerror (errno)); 139 exit (-1); 140 /* NOTREACHED */ 141 return 0; 142 143 default: 144 /* In the parent, after forking. 145 Close the descriptors that we made for this child. */ 146 if (input_desc != STDIN_FILE_NO) 147 close (input_desc); 148 if (output_desc != STDOUT_FILE_NO) 149 close (output_desc); 150 151 /* Return child's process number. */ 152 return pid; 153 } 154 } 155 156 int 157 pwait (pid, status, flags) 158 int pid; 159 int *status; 160 int flags ATTRIBUTE_UNUSED; 161 { 162 /* ??? Here's an opportunity to canonicalize the values in STATUS. 163 Needed? */ 164 pid = waitpid (pid, status, 0); 165 return pid; 166 } 167