1169695Skan/* Utilities to execute a program in a subprocess (possibly linked by pipes 2169695Skan with other subprocesses), and wait for it. DJGPP specialization. 3169695Skan Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2005 4169695Skan Free Software Foundation, Inc. 5169695Skan 6169695SkanThis file is part of the libiberty library. 7169695SkanLibiberty is free software; you can redistribute it and/or 8169695Skanmodify it under the terms of the GNU Library General Public 9169695SkanLicense as published by the Free Software Foundation; either 10169695Skanversion 2 of the License, or (at your option) any later version. 11169695Skan 12169695SkanLibiberty is distributed in the hope that it will be useful, 13169695Skanbut WITHOUT ANY WARRANTY; without even the implied warranty of 14169695SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15169695SkanLibrary General Public License for more details. 16169695Skan 17169695SkanYou should have received a copy of the GNU Library General Public 18169695SkanLicense along with libiberty; see the file COPYING.LIB. If not, 19169695Skanwrite to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 20169695SkanBoston, MA 02110-1301, USA. */ 21169695Skan 22169695Skan#include "pex-common.h" 23169695Skan 24169695Skan#include <stdio.h> 25169695Skan#include <errno.h> 26169695Skan#ifdef NEED_DECLARATION_ERRNO 27169695Skanextern int errno; 28169695Skan#endif 29169695Skan#ifdef HAVE_STDLIB_H 30169695Skan#include <stdlib.h> 31169695Skan#endif 32169695Skan#include <string.h> 33169695Skan#include <fcntl.h> 34169695Skan#include <unistd.h> 35169695Skan#include <sys/stat.h> 36169695Skan#include <process.h> 37169695Skan 38169695Skan/* Use ECHILD if available, otherwise use EINVAL. */ 39169695Skan#ifdef ECHILD 40169695Skan#define PWAIT_ERROR ECHILD 41169695Skan#else 42169695Skan#define PWAIT_ERROR EINVAL 43169695Skan#endif 44169695Skan 45169695Skanstatic int pex_djgpp_open_read (struct pex_obj *, const char *, int); 46169695Skanstatic int pex_djgpp_open_write (struct pex_obj *, const char *, int); 47169695Skanstatic long pex_djgpp_exec_child (struct pex_obj *, int, const char *, 48169695Skan char * const *, char * const *, 49169695Skan int, int, int, int, 50169695Skan const char **, int *); 51169695Skanstatic int pex_djgpp_close (struct pex_obj *, int); 52169695Skanstatic int pex_djgpp_wait (struct pex_obj *, long, int *, struct pex_time *, 53169695Skan int, const char **, int *); 54169695Skan 55169695Skan/* The list of functions we pass to the common routines. */ 56169695Skan 57169695Skanconst struct pex_funcs funcs = 58169695Skan{ 59169695Skan pex_djgpp_open_read, 60169695Skan pex_djgpp_open_write, 61169695Skan pex_djgpp_exec_child, 62169695Skan pex_djgpp_close, 63169695Skan pex_djgpp_wait, 64169695Skan NULL, /* pipe */ 65169695Skan NULL, /* fdopenr */ 66169695Skan NULL, /* fdopenw */ 67169695Skan NULL /* cleanup */ 68169695Skan}; 69169695Skan 70169695Skan/* Return a newly initialized pex_obj structure. */ 71169695Skan 72169695Skanstruct pex_obj * 73169695Skanpex_init (int flags, const char *pname, const char *tempbase) 74169695Skan{ 75169695Skan /* DJGPP does not support pipes. */ 76169695Skan flags &= ~ PEX_USE_PIPES; 77169695Skan return pex_init_common (flags, pname, tempbase, &funcs); 78169695Skan} 79169695Skan 80169695Skan/* Open a file for reading. */ 81169695Skan 82169695Skanstatic int 83169695Skanpex_djgpp_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, 84169695Skan const char *name, int binary) 85169695Skan{ 86169695Skan return open (name, O_RDONLY | (binary ? O_BINARY : O_TEXT)); 87169695Skan} 88169695Skan 89169695Skan/* Open a file for writing. */ 90169695Skan 91169695Skanstatic int 92169695Skanpex_djgpp_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, 93169695Skan const char *name, int binary) 94169695Skan{ 95169695Skan /* Note that we can't use O_EXCL here because gcc may have already 96169695Skan created the temporary file via make_temp_file. */ 97169695Skan return open (name, 98169695Skan (O_WRONLY | O_CREAT | O_TRUNC 99169695Skan | (binary ? O_BINARY : O_TEXT)), 100169695Skan S_IRUSR | S_IWUSR); 101169695Skan} 102169695Skan 103169695Skan/* Close a file. */ 104169695Skan 105169695Skanstatic int 106169695Skanpex_djgpp_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd) 107169695Skan{ 108169695Skan return close (fd); 109169695Skan} 110169695Skan 111169695Skan/* Execute a child. */ 112169695Skan 113169695Skanstatic long 114169695Skanpex_djgpp_exec_child (struct pex_obj *obj, int flags, const char *executable, 115169695Skan char * const * argv, char * const * env, 116169695Skan int in, int out, int errdes, 117169695Skan int toclose ATTRIBUTE_UNUSED, const char **errmsg, 118169695Skan int *err) 119169695Skan{ 120169695Skan int org_in, org_out, org_errdes; 121169695Skan int status; 122169695Skan int *statuses; 123169695Skan 124169695Skan org_in = -1; 125169695Skan org_out = -1; 126169695Skan org_errdes = -1; 127169695Skan 128169695Skan if (in != STDIN_FILE_NO) 129169695Skan { 130169695Skan org_in = dup (STDIN_FILE_NO); 131169695Skan if (org_in < 0) 132169695Skan { 133169695Skan *err = errno; 134169695Skan *errmsg = "dup"; 135169695Skan return -1; 136169695Skan } 137169695Skan if (dup2 (in, STDIN_FILE_NO) < 0) 138169695Skan { 139169695Skan *err = errno; 140169695Skan *errmsg = "dup2"; 141169695Skan return -1; 142169695Skan } 143169695Skan if (close (in) < 0) 144169695Skan { 145169695Skan *err = errno; 146169695Skan *errmsg = "close"; 147169695Skan return -1; 148169695Skan } 149169695Skan } 150169695Skan 151169695Skan if (out != STDOUT_FILE_NO) 152169695Skan { 153169695Skan org_out = dup (STDOUT_FILE_NO); 154169695Skan if (org_out < 0) 155169695Skan { 156169695Skan *err = errno; 157169695Skan *errmsg = "dup"; 158169695Skan return -1; 159169695Skan } 160169695Skan if (dup2 (out, STDOUT_FILE_NO) < 0) 161169695Skan { 162169695Skan *err = errno; 163169695Skan *errmsg = "dup2"; 164169695Skan return -1; 165169695Skan } 166169695Skan if (close (out) < 0) 167169695Skan { 168169695Skan *err = errno; 169169695Skan *errmsg = "close"; 170169695Skan return -1; 171169695Skan } 172169695Skan } 173169695Skan 174169695Skan if (errdes != STDERR_FILE_NO 175169695Skan || (flags & PEX_STDERR_TO_STDOUT) != 0) 176169695Skan { 177169695Skan org_errdes = dup (STDERR_FILE_NO); 178169695Skan if (org_errdes < 0) 179169695Skan { 180169695Skan *err = errno; 181169695Skan *errmsg = "dup"; 182169695Skan return -1; 183169695Skan } 184169695Skan if (dup2 ((flags & PEX_STDERR_TO_STDOUT) != 0 ? STDOUT_FILE_NO : errdes, 185169695Skan STDERR_FILE_NO) < 0) 186169695Skan { 187169695Skan *err = errno; 188169695Skan *errmsg = "dup2"; 189169695Skan return -1; 190169695Skan } 191169695Skan if (errdes != STDERR_FILE_NO) 192169695Skan { 193169695Skan if (close (errdes) < 0) 194169695Skan { 195169695Skan *err = errno; 196169695Skan *errmsg = "close"; 197169695Skan return -1; 198169695Skan } 199169695Skan } 200169695Skan } 201169695Skan 202169695Skan if (env) 203169695Skan status = (((flags & PEX_SEARCH) != 0 ? spawnvpe : spawnve) 204169695Skan (P_WAIT, executable, argv, env)); 205169695Skan else 206169695Skan status = (((flags & PEX_SEARCH) != 0 ? spawnvp : spawnv) 207169695Skan (P_WAIT, executable, argv)); 208169695Skan 209169695Skan if (status == -1) 210169695Skan { 211169695Skan *err = errno; 212169695Skan *errmsg = ((flags & PEX_SEARCH) != 0) ? "spawnvp" : "spawnv"; 213169695Skan } 214169695Skan 215169695Skan if (in != STDIN_FILE_NO) 216169695Skan { 217169695Skan if (dup2 (org_in, STDIN_FILE_NO) < 0) 218169695Skan { 219169695Skan *err = errno; 220169695Skan *errmsg = "dup2"; 221169695Skan return -1; 222169695Skan } 223169695Skan if (close (org_in) < 0) 224169695Skan { 225169695Skan *err = errno; 226169695Skan *errmsg = "close"; 227169695Skan return -1; 228169695Skan } 229169695Skan } 230169695Skan 231169695Skan if (out != STDOUT_FILE_NO) 232169695Skan { 233169695Skan if (dup2 (org_out, STDOUT_FILE_NO) < 0) 234169695Skan { 235169695Skan *err = errno; 236169695Skan *errmsg = "dup2"; 237169695Skan return -1; 238169695Skan } 239169695Skan if (close (org_out) < 0) 240169695Skan { 241169695Skan *err = errno; 242169695Skan *errmsg = "close"; 243169695Skan return -1; 244169695Skan } 245169695Skan } 246169695Skan 247169695Skan if (errdes != STDERR_FILE_NO 248169695Skan || (flags & PEX_STDERR_TO_STDOUT) != 0) 249169695Skan { 250169695Skan if (dup2 (org_errdes, STDERR_FILE_NO) < 0) 251169695Skan { 252169695Skan *err = errno; 253169695Skan *errmsg = "dup2"; 254169695Skan return -1; 255169695Skan } 256169695Skan if (close (org_errdes) < 0) 257169695Skan { 258169695Skan *err = errno; 259169695Skan *errmsg = "close"; 260169695Skan return -1; 261169695Skan } 262169695Skan } 263169695Skan 264169695Skan /* Save the exit status for later. When we are called, obj->count 265169695Skan is the number of children which have executed before this 266169695Skan one. */ 267169695Skan statuses = (int *) obj->sysdep; 268169695Skan statuses = XRESIZEVEC (int, statuses, obj->count + 1); 269169695Skan statuses[obj->count] = status; 270169695Skan obj->sysdep = (void *) statuses; 271169695Skan 272169695Skan return obj->count; 273169695Skan} 274169695Skan 275169695Skan/* Wait for a child process to complete. Actually the child process 276169695Skan has already completed, and we just need to return the exit 277169695Skan status. */ 278169695Skan 279169695Skanstatic int 280169695Skanpex_djgpp_wait (struct pex_obj *obj, long pid, int *status, 281169695Skan struct pex_time *time, int done ATTRIBUTE_UNUSED, 282169695Skan const char **errmsg ATTRIBUTE_UNUSED, 283169695Skan int *err ATTRIBUTE_UNUSED) 284169695Skan{ 285169695Skan int *statuses; 286169695Skan 287169695Skan if (time != NULL) 288169695Skan memset (time, 0, sizeof *time); 289169695Skan 290169695Skan statuses = (int *) obj->sysdep; 291169695Skan *status = statuses[pid]; 292169695Skan 293169695Skan return 0; 294169695Skan} 295