1 /* Utilities to execute a program in a subprocess (possibly linked by pipes 2 with other subprocesses), and wait for it. DJGPP specialization. 3 Copyright (C) 1996-2020 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., 51 Franklin Street - Fifth Floor, 19 Boston, MA 02110-1301, USA. */ 20 21 #include "pex-common.h" 22 23 #include <stdio.h> 24 #include <errno.h> 25 #ifdef NEED_DECLARATION_ERRNO 26 extern int errno; 27 #endif 28 #ifdef HAVE_STDLIB_H 29 #include <stdlib.h> 30 #endif 31 #include <string.h> 32 #include <fcntl.h> 33 #include <unistd.h> 34 #include <sys/stat.h> 35 #include <process.h> 36 37 /* Use ECHILD if available, otherwise use EINVAL. */ 38 #ifdef ECHILD 39 #define PWAIT_ERROR ECHILD 40 #else 41 #define PWAIT_ERROR EINVAL 42 #endif 43 44 static int pex_djgpp_open_read (struct pex_obj *, const char *, int); 45 static int pex_djgpp_open_write (struct pex_obj *, const char *, int, int); 46 static pid_t pex_djgpp_exec_child (struct pex_obj *, int, const char *, 47 char * const *, char * const *, 48 int, int, int, int, 49 const char **, int *); 50 static int pex_djgpp_close (struct pex_obj *, int); 51 static pid_t pex_djgpp_wait (struct pex_obj *, pid_t, int *, struct pex_time *, 52 int, const char **, int *); 53 54 /* The list of functions we pass to the common routines. */ 55 56 const struct pex_funcs funcs = 57 { 58 pex_djgpp_open_read, 59 pex_djgpp_open_write, 60 pex_djgpp_exec_child, 61 pex_djgpp_close, 62 pex_djgpp_wait, 63 NULL, /* pipe */ 64 NULL, /* fdopenr */ 65 NULL, /* fdopenw */ 66 NULL /* cleanup */ 67 }; 68 69 /* Return a newly initialized pex_obj structure. */ 70 71 struct pex_obj * 72 pex_init (int flags, const char *pname, const char *tempbase) 73 { 74 /* DJGPP does not support pipes. */ 75 flags &= ~ PEX_USE_PIPES; 76 return pex_init_common (flags, pname, tempbase, &funcs); 77 } 78 79 /* Open a file for reading. */ 80 81 static int 82 pex_djgpp_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, 83 const char *name, int binary) 84 { 85 return open (name, O_RDONLY | (binary ? O_BINARY : O_TEXT)); 86 } 87 88 /* Open a file for writing. */ 89 90 static int 91 pex_djgpp_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, 92 const char *name, int binary, int append) 93 { 94 /* Note that we can't use O_EXCL here because gcc may have already 95 created the temporary file via make_temp_file. */ 96 if (append) 97 return -1; 98 return open (name, 99 (O_WRONLY | O_CREAT | O_TRUNC 100 | (binary ? O_BINARY : O_TEXT)), 101 S_IRUSR | S_IWUSR); 102 } 103 104 /* Close a file. */ 105 106 static int 107 pex_djgpp_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd) 108 { 109 return close (fd); 110 } 111 112 /* Execute a child. */ 113 114 static pid_t 115 pex_djgpp_exec_child (struct pex_obj *obj, int flags, const char *executable, 116 char * const * argv, char * const * env, 117 int in, int out, int errdes, 118 int toclose ATTRIBUTE_UNUSED, const char **errmsg, 119 int *err) 120 { 121 int org_in, org_out, org_errdes; 122 int status; 123 int *statuses; 124 125 org_in = -1; 126 org_out = -1; 127 org_errdes = -1; 128 129 if (in != STDIN_FILE_NO) 130 { 131 org_in = dup (STDIN_FILE_NO); 132 if (org_in < 0) 133 { 134 *err = errno; 135 *errmsg = "dup"; 136 return (pid_t) -1; 137 } 138 if (dup2 (in, STDIN_FILE_NO) < 0) 139 { 140 *err = errno; 141 *errmsg = "dup2"; 142 return (pid_t) -1; 143 } 144 if (close (in) < 0) 145 { 146 *err = errno; 147 *errmsg = "close"; 148 return (pid_t) -1; 149 } 150 } 151 152 if (out != STDOUT_FILE_NO) 153 { 154 org_out = dup (STDOUT_FILE_NO); 155 if (org_out < 0) 156 { 157 *err = errno; 158 *errmsg = "dup"; 159 return (pid_t) -1; 160 } 161 if (dup2 (out, STDOUT_FILE_NO) < 0) 162 { 163 *err = errno; 164 *errmsg = "dup2"; 165 return (pid_t) -1; 166 } 167 if (close (out) < 0) 168 { 169 *err = errno; 170 *errmsg = "close"; 171 return (pid_t) -1; 172 } 173 } 174 175 if (errdes != STDERR_FILE_NO 176 || (flags & PEX_STDERR_TO_STDOUT) != 0) 177 { 178 org_errdes = dup (STDERR_FILE_NO); 179 if (org_errdes < 0) 180 { 181 *err = errno; 182 *errmsg = "dup"; 183 return (pid_t) -1; 184 } 185 if (dup2 ((flags & PEX_STDERR_TO_STDOUT) != 0 ? STDOUT_FILE_NO : errdes, 186 STDERR_FILE_NO) < 0) 187 { 188 *err = errno; 189 *errmsg = "dup2"; 190 return (pid_t) -1; 191 } 192 if (errdes != STDERR_FILE_NO) 193 { 194 if (close (errdes) < 0) 195 { 196 *err = errno; 197 *errmsg = "close"; 198 return (pid_t) -1; 199 } 200 } 201 } 202 203 if (env) 204 status = (((flags & PEX_SEARCH) != 0 ? spawnvpe : spawnve) 205 (P_WAIT, executable, argv, env)); 206 else 207 status = (((flags & PEX_SEARCH) != 0 ? spawnvp : spawnv) 208 (P_WAIT, executable, argv)); 209 210 if (status == -1) 211 { 212 *err = errno; 213 *errmsg = ((flags & PEX_SEARCH) != 0) ? "spawnvp" : "spawnv"; 214 } 215 216 if (in != STDIN_FILE_NO) 217 { 218 if (dup2 (org_in, STDIN_FILE_NO) < 0) 219 { 220 *err = errno; 221 *errmsg = "dup2"; 222 return (pid_t) -1; 223 } 224 if (close (org_in) < 0) 225 { 226 *err = errno; 227 *errmsg = "close"; 228 return (pid_t) -1; 229 } 230 } 231 232 if (out != STDOUT_FILE_NO) 233 { 234 if (dup2 (org_out, STDOUT_FILE_NO) < 0) 235 { 236 *err = errno; 237 *errmsg = "dup2"; 238 return (pid_t) -1; 239 } 240 if (close (org_out) < 0) 241 { 242 *err = errno; 243 *errmsg = "close"; 244 return (pid_t) -1; 245 } 246 } 247 248 if (errdes != STDERR_FILE_NO 249 || (flags & PEX_STDERR_TO_STDOUT) != 0) 250 { 251 if (dup2 (org_errdes, STDERR_FILE_NO) < 0) 252 { 253 *err = errno; 254 *errmsg = "dup2"; 255 return (pid_t) -1; 256 } 257 if (close (org_errdes) < 0) 258 { 259 *err = errno; 260 *errmsg = "close"; 261 return (pid_t) -1; 262 } 263 } 264 265 /* Save the exit status for later. When we are called, obj->count 266 is the number of children which have executed before this 267 one. */ 268 statuses = (int *) obj->sysdep; 269 statuses = XRESIZEVEC (int, statuses, obj->count + 1); 270 statuses[obj->count] = status; 271 obj->sysdep = (void *) statuses; 272 273 return (pid_t) obj->count; 274 } 275 276 /* Wait for a child process to complete. Actually the child process 277 has already completed, and we just need to return the exit 278 status. */ 279 280 static pid_t 281 pex_djgpp_wait (struct pex_obj *obj, pid_t pid, int *status, 282 struct pex_time *time, int done ATTRIBUTE_UNUSED, 283 const char **errmsg ATTRIBUTE_UNUSED, 284 int *err ATTRIBUTE_UNUSED) 285 { 286 int *statuses; 287 288 if (time != NULL) 289 memset (time, 0, sizeof *time); 290 291 statuses = (int *) obj->sysdep; 292 *status = statuses[pid]; 293 294 return 0; 295 } 296