1169695Skan/* Utilities to execute a program in a subprocess (possibly linked by pipes 2169695Skan with other subprocesses), and wait for it. Generic Win32 specialization. 3169695Skan Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 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 <windows.h> 25169695Skan 26169695Skan#ifdef HAVE_STDLIB_H 27169695Skan#include <stdlib.h> 28169695Skan#endif 29169695Skan#ifdef HAVE_STRING_H 30169695Skan#include <string.h> 31169695Skan#endif 32169695Skan#ifdef HAVE_UNISTD_H 33169695Skan#include <unistd.h> 34169695Skan#endif 35169695Skan#ifdef HAVE_SYS_WAIT_H 36169695Skan#include <sys/wait.h> 37169695Skan#endif 38169695Skan 39169695Skan#include <assert.h> 40169695Skan#include <process.h> 41169695Skan#include <io.h> 42169695Skan#include <fcntl.h> 43169695Skan#include <signal.h> 44169695Skan#include <sys/stat.h> 45169695Skan#include <errno.h> 46169695Skan#include <ctype.h> 47169695Skan 48169695Skan/* mingw32 headers may not define the following. */ 49169695Skan 50169695Skan#ifndef _P_WAIT 51169695Skan# define _P_WAIT 0 52169695Skan# define _P_NOWAIT 1 53169695Skan# define _P_OVERLAY 2 54169695Skan# define _P_NOWAITO 3 55169695Skan# define _P_DETACH 4 56169695Skan 57169695Skan# define WAIT_CHILD 0 58169695Skan# define WAIT_GRANDCHILD 1 59169695Skan#endif 60169695Skan 61169695Skan#define MINGW_NAME "Minimalist GNU for Windows" 62169695Skan#define MINGW_NAME_LEN (sizeof(MINGW_NAME) - 1) 63169695Skan 64169695Skanextern char *stpcpy (char *dst, const char *src); 65169695Skan 66169695Skan/* Ensure that the executable pathname uses Win32 backslashes. This 67169695Skan is not necessary on NT, but on W9x, forward slashes causes 68169695Skan failure of spawn* and exec* functions (and probably any function 69169695Skan that calls CreateProcess) *iff* the executable pathname (argv[0]) 70169695Skan is a quoted string. And quoting is necessary in case a pathname 71169695Skan contains embedded white space. You can't win. */ 72169695Skanstatic void 73169695Skanbackslashify (char *s) 74169695Skan{ 75169695Skan while ((s = strchr (s, '/')) != NULL) 76169695Skan *s = '\\'; 77169695Skan return; 78169695Skan} 79169695Skan 80169695Skanstatic int pex_win32_open_read (struct pex_obj *, const char *, int); 81169695Skanstatic int pex_win32_open_write (struct pex_obj *, const char *, int); 82169695Skanstatic long pex_win32_exec_child (struct pex_obj *, int, const char *, 83169695Skan char * const *, char * const *, 84169695Skan int, int, int, int, 85169695Skan const char **, int *); 86169695Skanstatic int pex_win32_close (struct pex_obj *, int); 87169695Skanstatic int pex_win32_wait (struct pex_obj *, long, int *, 88169695Skan struct pex_time *, int, const char **, int *); 89169695Skanstatic int pex_win32_pipe (struct pex_obj *, int *, int); 90169695Skanstatic FILE *pex_win32_fdopenr (struct pex_obj *, int, int); 91169695Skanstatic FILE *pex_win32_fdopenw (struct pex_obj *, int, int); 92169695Skan 93169695Skan/* The list of functions we pass to the common routines. */ 94169695Skan 95169695Skanconst struct pex_funcs funcs = 96169695Skan{ 97169695Skan pex_win32_open_read, 98169695Skan pex_win32_open_write, 99169695Skan pex_win32_exec_child, 100169695Skan pex_win32_close, 101169695Skan pex_win32_wait, 102169695Skan pex_win32_pipe, 103169695Skan pex_win32_fdopenr, 104169695Skan pex_win32_fdopenw, 105169695Skan NULL /* cleanup */ 106169695Skan}; 107169695Skan 108169695Skan/* Return a newly initialized pex_obj structure. */ 109169695Skan 110169695Skanstruct pex_obj * 111169695Skanpex_init (int flags, const char *pname, const char *tempbase) 112169695Skan{ 113169695Skan return pex_init_common (flags, pname, tempbase, &funcs); 114169695Skan} 115169695Skan 116169695Skan/* Open a file for reading. */ 117169695Skan 118169695Skanstatic int 119169695Skanpex_win32_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, 120169695Skan int binary) 121169695Skan{ 122169695Skan return _open (name, _O_RDONLY | (binary ? _O_BINARY : _O_TEXT)); 123169695Skan} 124169695Skan 125169695Skan/* Open a file for writing. */ 126169695Skan 127169695Skanstatic int 128169695Skanpex_win32_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, 129169695Skan int binary) 130169695Skan{ 131169695Skan /* Note that we can't use O_EXCL here because gcc may have already 132169695Skan created the temporary file via make_temp_file. */ 133169695Skan return _open (name, 134169695Skan (_O_WRONLY | _O_CREAT | _O_TRUNC 135169695Skan | (binary ? _O_BINARY : _O_TEXT)), 136169695Skan _S_IREAD | _S_IWRITE); 137169695Skan} 138169695Skan 139169695Skan/* Close a file. */ 140169695Skan 141169695Skanstatic int 142169695Skanpex_win32_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd) 143169695Skan{ 144169695Skan return _close (fd); 145169695Skan} 146169695Skan 147169695Skan#ifdef USE_MINGW_MSYS 148169695Skanstatic const char *mingw_keys[] = {"SOFTWARE", "Microsoft", "Windows", "CurrentVersion", "Uninstall", NULL}; 149169695Skan 150169695Skan/* Tack the executable on the end of a (possibly slash terminated) buffer 151169695Skan and convert everything to \. */ 152169695Skanstatic const char * 153169695Skantack_on_executable (char *buf, const char *executable) 154169695Skan{ 155169695Skan char *p = strchr (buf, '\0'); 156169695Skan if (p > buf && (p[-1] == '\\' || p[-1] == '/')) 157169695Skan p[-1] = '\0'; 158169695Skan backslashify (strcat (buf, executable)); 159169695Skan return buf; 160169695Skan} 161169695Skan 162169695Skan/* Walk down a registry hierarchy until the end. Return the key. */ 163169695Skanstatic HKEY 164169695Skanopenkey (HKEY hStart, const char *keys[]) 165169695Skan{ 166169695Skan HKEY hKey, hTmp; 167169695Skan for (hKey = hStart; *keys; keys++) 168169695Skan { 169169695Skan LONG res; 170169695Skan hTmp = hKey; 171169695Skan res = RegOpenKey (hTmp, *keys, &hKey); 172169695Skan 173169695Skan if (hTmp != HKEY_LOCAL_MACHINE) 174169695Skan RegCloseKey (hTmp); 175169695Skan 176169695Skan if (res != ERROR_SUCCESS) 177169695Skan return NULL; 178169695Skan } 179169695Skan return hKey; 180169695Skan} 181169695Skan 182169695Skan/* Return the "mingw root" as derived from the mingw uninstall information. */ 183169695Skanstatic const char * 184169695Skanmingw_rootify (const char *executable) 185169695Skan{ 186169695Skan HKEY hKey, hTmp; 187169695Skan DWORD maxlen; 188169695Skan char *namebuf, *foundbuf; 189169695Skan DWORD i; 190169695Skan LONG res; 191169695Skan 192169695Skan /* Open the uninstall "directory". */ 193169695Skan hKey = openkey (HKEY_LOCAL_MACHINE, mingw_keys); 194169695Skan 195169695Skan /* Not found. */ 196169695Skan if (!hKey) 197169695Skan return executable; 198169695Skan 199169695Skan /* Need to enumerate all of the keys here looking for one the most recent 200169695Skan one for MinGW. */ 201169695Skan if (RegQueryInfoKey (hKey, NULL, NULL, NULL, NULL, &maxlen, NULL, NULL, 202169695Skan NULL, NULL, NULL, NULL) != ERROR_SUCCESS) 203169695Skan { 204169695Skan RegCloseKey (hKey); 205169695Skan return executable; 206169695Skan } 207169695Skan namebuf = XNEWVEC (char, ++maxlen); 208169695Skan foundbuf = XNEWVEC (char, maxlen); 209169695Skan foundbuf[0] = '\0'; 210169695Skan if (!namebuf || !foundbuf) 211169695Skan { 212169695Skan RegCloseKey (hKey); 213169695Skan if (namebuf) 214169695Skan free (namebuf); 215169695Skan if (foundbuf) 216169695Skan free (foundbuf); 217169695Skan return executable; 218169695Skan } 219169695Skan 220169695Skan /* Look through all of the keys for one that begins with Minimal GNU... 221169695Skan Try to get the latest version by doing a string compare although that 222169695Skan string never really works with version number sorting. */ 223169695Skan for (i = 0; RegEnumKey (hKey, i, namebuf, maxlen) == ERROR_SUCCESS; i++) 224169695Skan { 225169695Skan int match = strcasecmp (namebuf, MINGW_NAME); 226169695Skan if (match < 0) 227169695Skan continue; 228169695Skan if (match > 0 && strncasecmp (namebuf, MINGW_NAME, MINGW_NAME_LEN) > 0) 229169695Skan continue; 230169695Skan if (strcasecmp (namebuf, foundbuf) > 0) 231169695Skan strcpy (foundbuf, namebuf); 232169695Skan } 233169695Skan free (namebuf); 234169695Skan 235169695Skan /* If foundbuf is empty, we didn't find anything. Punt. */ 236169695Skan if (!foundbuf[0]) 237169695Skan { 238169695Skan free (foundbuf); 239169695Skan RegCloseKey (hKey); 240169695Skan return executable; 241169695Skan } 242169695Skan 243169695Skan /* Open the key that we wanted */ 244169695Skan res = RegOpenKey (hKey, foundbuf, &hTmp); 245169695Skan RegCloseKey (hKey); 246169695Skan free (foundbuf); 247169695Skan 248169695Skan /* Don't know why this would fail, but you gotta check */ 249169695Skan if (res != ERROR_SUCCESS) 250169695Skan return executable; 251169695Skan 252169695Skan maxlen = 0; 253169695Skan /* Get the length of the value pointed to by InstallLocation */ 254169695Skan if (RegQueryValueEx (hTmp, "InstallLocation", 0, NULL, NULL, 255169695Skan &maxlen) != ERROR_SUCCESS || maxlen == 0) 256169695Skan { 257169695Skan RegCloseKey (hTmp); 258169695Skan return executable; 259169695Skan } 260169695Skan 261169695Skan /* Allocate space for the install location */ 262169695Skan foundbuf = XNEWVEC (char, maxlen + strlen (executable)); 263169695Skan if (!foundbuf) 264169695Skan { 265169695Skan free (foundbuf); 266169695Skan RegCloseKey (hTmp); 267169695Skan } 268169695Skan 269169695Skan /* Read the install location into the buffer */ 270169695Skan res = RegQueryValueEx (hTmp, "InstallLocation", 0, NULL, (LPBYTE) foundbuf, 271169695Skan &maxlen); 272169695Skan RegCloseKey (hTmp); 273169695Skan if (res != ERROR_SUCCESS) 274169695Skan { 275169695Skan free (foundbuf); 276169695Skan return executable; 277169695Skan } 278169695Skan 279169695Skan /* Concatenate the install location and the executable, turn all slashes 280169695Skan to backslashes, and return that. */ 281169695Skan return tack_on_executable (foundbuf, executable); 282169695Skan} 283169695Skan 284169695Skan/* Read the install location of msys from it's installation file and 285169695Skan rootify the executable based on that. */ 286169695Skanstatic const char * 287169695Skanmsys_rootify (const char *executable) 288169695Skan{ 289169695Skan size_t bufsize = 64; 290169695Skan size_t execlen = strlen (executable) + 1; 291169695Skan char *buf; 292169695Skan DWORD res = 0; 293169695Skan for (;;) 294169695Skan { 295169695Skan buf = XNEWVEC (char, bufsize + execlen); 296169695Skan if (!buf) 297169695Skan break; 298169695Skan res = GetPrivateProfileString ("InstallSettings", "InstallPath", NULL, 299169695Skan buf, bufsize, "msys.ini"); 300169695Skan if (!res) 301169695Skan break; 302169695Skan if (strlen (buf) < bufsize) 303169695Skan break; 304169695Skan res = 0; 305169695Skan free (buf); 306169695Skan bufsize *= 2; 307169695Skan if (bufsize > 65536) 308169695Skan { 309169695Skan buf = NULL; 310169695Skan break; 311169695Skan } 312169695Skan } 313169695Skan 314169695Skan if (res) 315169695Skan return tack_on_executable (buf, executable); 316169695Skan 317169695Skan /* failed */ 318169695Skan if (buf) 319169695Skan free (buf); 320169695Skan return executable; 321169695Skan} 322169695Skan#endif 323169695Skan 324169695Skan/* Return a Windows command-line from ARGV. It is the caller's 325169695Skan responsibility to free the string returned. */ 326169695Skan 327169695Skanstatic char * 328169695Skanargv_to_cmdline (char *const *argv) 329169695Skan{ 330169695Skan char *cmdline; 331169695Skan char *p; 332169695Skan size_t cmdline_len; 333169695Skan int i, j, k; 334169695Skan 335169695Skan cmdline_len = 0; 336169695Skan for (i = 0; argv[i]; i++) 337169695Skan { 338169695Skan /* We quote every last argument. This simplifies the problem; 339169695Skan we need only escape embedded double-quotes and immediately 340169695Skan preceeding backslash characters. A sequence of backslach characters 341169695Skan that is not follwed by a double quote character will not be 342169695Skan escaped. */ 343169695Skan for (j = 0; argv[i][j]; j++) 344169695Skan { 345169695Skan if (argv[i][j] == '"') 346169695Skan { 347169695Skan /* Escape preceeding backslashes. */ 348169695Skan for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--) 349169695Skan cmdline_len++; 350169695Skan /* Escape the qote character. */ 351169695Skan cmdline_len++; 352169695Skan } 353169695Skan } 354169695Skan /* Trailing backslashes also need to be escaped because they will be 355169695Skan followed by the terminating quote. */ 356169695Skan for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--) 357169695Skan cmdline_len++; 358169695Skan cmdline_len += j; 359169695Skan cmdline_len += 3; /* for leading and trailing quotes and space */ 360169695Skan } 361169695Skan cmdline = xmalloc (cmdline_len); 362169695Skan p = cmdline; 363169695Skan for (i = 0; argv[i]; i++) 364169695Skan { 365169695Skan *p++ = '"'; 366169695Skan for (j = 0; argv[i][j]; j++) 367169695Skan { 368169695Skan if (argv[i][j] == '"') 369169695Skan { 370169695Skan for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--) 371169695Skan *p++ = '\\'; 372169695Skan *p++ = '\\'; 373169695Skan } 374169695Skan *p++ = argv[i][j]; 375169695Skan } 376169695Skan for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--) 377169695Skan *p++ = '\\'; 378169695Skan *p++ = '"'; 379169695Skan *p++ = ' '; 380169695Skan } 381169695Skan p[-1] = '\0'; 382169695Skan return cmdline; 383169695Skan} 384169695Skan 385169695Skanstatic const char *const 386169695Skanstd_suffixes[] = { 387169695Skan ".com", 388169695Skan ".exe", 389169695Skan ".bat", 390169695Skan ".cmd", 391169695Skan 0 392169695Skan}; 393169695Skanstatic const char *const 394169695Skanno_suffixes[] = { 395169695Skan "", 396169695Skan 0 397169695Skan}; 398169695Skan 399169695Skan/* Returns the full path to PROGRAM. If SEARCH is true, look for 400169695Skan PROGRAM in each directory in PATH. */ 401169695Skan 402169695Skanstatic char * 403169695Skanfind_executable (const char *program, BOOL search) 404169695Skan{ 405169695Skan char *full_executable; 406169695Skan char *e; 407169695Skan size_t fe_len; 408169695Skan const char *path = 0; 409169695Skan const char *const *ext; 410169695Skan const char *p, *q; 411169695Skan size_t proglen = strlen (program); 412169695Skan int has_extension = !!strchr (program, '.'); 413169695Skan int has_slash = (strchr (program, '/') || strchr (program, '\\')); 414169695Skan HANDLE h; 415169695Skan 416169695Skan if (has_slash) 417169695Skan search = FALSE; 418169695Skan 419169695Skan if (search) 420169695Skan path = getenv ("PATH"); 421169695Skan if (!path) 422169695Skan path = ""; 423169695Skan 424169695Skan fe_len = 0; 425169695Skan for (p = path; *p; p = q) 426169695Skan { 427169695Skan q = p; 428169695Skan while (*q != ';' && *q != '\0') 429169695Skan q++; 430169695Skan if ((size_t)(q - p) > fe_len) 431169695Skan fe_len = q - p; 432169695Skan if (*q == ';') 433169695Skan q++; 434169695Skan } 435169695Skan fe_len = fe_len + 1 + proglen + (has_extension ? 1 : 5); 436169695Skan full_executable = xmalloc (fe_len); 437169695Skan 438169695Skan p = path; 439169695Skan do 440169695Skan { 441169695Skan q = p; 442169695Skan while (*q != ';' && *q != '\0') 443169695Skan q++; 444169695Skan 445169695Skan e = full_executable; 446169695Skan memcpy (e, p, q - p); 447169695Skan e += (q - p); 448169695Skan if (q - p) 449169695Skan *e++ = '\\'; 450169695Skan strcpy (e, program); 451169695Skan 452169695Skan if (*q == ';') 453169695Skan q++; 454169695Skan 455169695Skan for (e = full_executable; *e; e++) 456169695Skan if (*e == '/') 457169695Skan *e = '\\'; 458169695Skan 459169695Skan /* At this point, e points to the terminating NUL character for 460169695Skan full_executable. */ 461169695Skan for (ext = has_extension ? no_suffixes : std_suffixes; *ext; ext++) 462169695Skan { 463169695Skan /* Remove any current extension. */ 464169695Skan *e = '\0'; 465169695Skan /* Add the new one. */ 466169695Skan strcat (full_executable, *ext); 467169695Skan 468169695Skan /* Attempt to open this file. */ 469169695Skan h = CreateFile (full_executable, GENERIC_READ, 470169695Skan FILE_SHARE_READ | FILE_SHARE_WRITE, 471169695Skan 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); 472169695Skan if (h != INVALID_HANDLE_VALUE) 473169695Skan goto found; 474169695Skan } 475169695Skan p = q; 476169695Skan } 477169695Skan while (*p); 478169695Skan free (full_executable); 479169695Skan return 0; 480169695Skan 481169695Skan found: 482169695Skan CloseHandle (h); 483169695Skan return full_executable; 484169695Skan} 485169695Skan 486169695Skan/* Low-level process creation function and helper. */ 487169695Skan 488169695Skanstatic int 489169695Skanenv_compare (const void *a_ptr, const void *b_ptr) 490169695Skan{ 491169695Skan const char *a; 492169695Skan const char *b; 493169695Skan unsigned char c1; 494169695Skan unsigned char c2; 495169695Skan 496169695Skan a = *(const char **) a_ptr; 497169695Skan b = *(const char **) b_ptr; 498169695Skan 499169695Skan /* a and b will be of the form: VAR=VALUE 500169695Skan We compare only the variable name part here using a case-insensitive 501169695Skan comparison algorithm. It might appear that in fact strcasecmp () can 502169695Skan take the place of this whole function, and indeed it could, save for 503169695Skan the fact that it would fail in cases such as comparing A1=foo and 504169695Skan A=bar (because 1 is less than = in the ASCII character set). 505169695Skan (Environment variables containing no numbers would work in such a 506169695Skan scenario.) */ 507169695Skan 508169695Skan do 509169695Skan { 510169695Skan c1 = (unsigned char) tolower (*a++); 511169695Skan c2 = (unsigned char) tolower (*b++); 512169695Skan 513169695Skan if (c1 == '=') 514169695Skan c1 = '\0'; 515169695Skan 516169695Skan if (c2 == '=') 517169695Skan c2 = '\0'; 518169695Skan } 519169695Skan while (c1 == c2 && c1 != '\0'); 520169695Skan 521169695Skan return c1 - c2; 522169695Skan} 523169695Skan 524169695Skanstatic long 525169695Skanwin32_spawn (const char *executable, 526169695Skan BOOL search, 527169695Skan char *const *argv, 528169695Skan char *const *env, /* array of strings of the form: VAR=VALUE */ 529169695Skan DWORD dwCreationFlags, 530169695Skan LPSTARTUPINFO si, 531169695Skan LPPROCESS_INFORMATION pi) 532169695Skan{ 533169695Skan char *full_executable; 534169695Skan char *cmdline; 535169695Skan char **env_copy; 536169695Skan char *env_block = NULL; 537169695Skan 538169695Skan full_executable = NULL; 539169695Skan cmdline = NULL; 540169695Skan 541169695Skan if (env) 542169695Skan { 543169695Skan int env_size; 544169695Skan 545169695Skan /* Count the number of environment bindings supplied. */ 546169695Skan for (env_size = 0; env[env_size]; env_size++) 547169695Skan continue; 548169695Skan 549169695Skan /* Assemble an environment block, if required. This consists of 550169695Skan VAR=VALUE strings juxtaposed (with one null character between each 551169695Skan pair) and an additional null at the end. */ 552169695Skan if (env_size > 0) 553169695Skan { 554169695Skan int var; 555169695Skan int total_size = 1; /* 1 is for the final null. */ 556169695Skan char *bufptr; 557169695Skan 558169695Skan /* Windows needs the members of the block to be sorted by variable 559169695Skan name. */ 560169695Skan env_copy = alloca (sizeof (char *) * env_size); 561169695Skan memcpy (env_copy, env, sizeof (char *) * env_size); 562169695Skan qsort (env_copy, env_size, sizeof (char *), env_compare); 563169695Skan 564169695Skan for (var = 0; var < env_size; var++) 565169695Skan total_size += strlen (env[var]) + 1; 566169695Skan 567169695Skan env_block = malloc (total_size); 568169695Skan bufptr = env_block; 569169695Skan for (var = 0; var < env_size; var++) 570169695Skan bufptr = stpcpy (bufptr, env_copy[var]) + 1; 571169695Skan 572169695Skan *bufptr = '\0'; 573169695Skan } 574169695Skan } 575169695Skan 576169695Skan full_executable = find_executable (executable, search); 577169695Skan if (!full_executable) 578169695Skan goto error; 579169695Skan cmdline = argv_to_cmdline (argv); 580169695Skan if (!cmdline) 581169695Skan goto error; 582169695Skan 583169695Skan /* Create the child process. */ 584169695Skan if (!CreateProcess (full_executable, cmdline, 585169695Skan /*lpProcessAttributes=*/NULL, 586169695Skan /*lpThreadAttributes=*/NULL, 587169695Skan /*bInheritHandles=*/TRUE, 588169695Skan dwCreationFlags, 589169695Skan (LPVOID) env_block, 590169695Skan /*lpCurrentDirectory=*/NULL, 591169695Skan si, 592169695Skan pi)) 593169695Skan { 594169695Skan if (env_block) 595169695Skan free (env_block); 596169695Skan 597169695Skan free (full_executable); 598169695Skan 599169695Skan return -1; 600169695Skan } 601169695Skan 602169695Skan /* Clean up. */ 603169695Skan CloseHandle (pi->hThread); 604169695Skan free (full_executable); 605169695Skan if (env_block) 606169695Skan free (env_block); 607169695Skan 608169695Skan return (long) pi->hProcess; 609169695Skan 610169695Skan error: 611169695Skan if (env_block) 612169695Skan free (env_block); 613169695Skan if (cmdline) 614169695Skan free (cmdline); 615169695Skan if (full_executable) 616169695Skan free (full_executable); 617169695Skan 618169695Skan return -1; 619169695Skan} 620169695Skan 621169695Skanstatic long 622169695Skanspawn_script (const char *executable, char *const *argv, 623169695Skan char* const *env, 624169695Skan DWORD dwCreationFlags, 625169695Skan LPSTARTUPINFO si, 626169695Skan LPPROCESS_INFORMATION pi) 627169695Skan{ 628169695Skan int pid = -1; 629169695Skan int save_errno = errno; 630169695Skan int fd = _open (executable, _O_RDONLY); 631169695Skan 632169695Skan if (fd >= 0) 633169695Skan { 634169695Skan char buf[MAX_PATH + 5]; 635169695Skan int len = _read (fd, buf, sizeof (buf) - 1); 636169695Skan _close (fd); 637169695Skan if (len > 3) 638169695Skan { 639169695Skan char *eol; 640169695Skan buf[len] = '\0'; 641169695Skan eol = strchr (buf, '\n'); 642169695Skan if (eol && strncmp (buf, "#!", 2) == 0) 643169695Skan { 644169695Skan char *executable1; 645169695Skan const char ** avhere = (const char **) --argv; 646169695Skan do 647169695Skan *eol = '\0'; 648169695Skan while (*--eol == '\r' || *eol == ' ' || *eol == '\t'); 649169695Skan for (executable1 = buf + 2; *executable1 == ' ' || *executable1 == '\t'; executable1++) 650169695Skan continue; 651169695Skan 652169695Skan backslashify (executable1); 653169695Skan *avhere = executable1; 654169695Skan#ifndef USE_MINGW_MSYS 655169695Skan executable = strrchr (executable1, '\\') + 1; 656169695Skan if (!executable) 657169695Skan executable = executable1; 658169695Skan pid = win32_spawn (executable, TRUE, argv, env, 659169695Skan dwCreationFlags, si, pi); 660169695Skan#else 661169695Skan if (strchr (executable1, '\\') == NULL) 662169695Skan pid = win32_spawn (executable1, TRUE, argv, env, 663169695Skan dwCreationFlags, si, pi); 664169695Skan else if (executable1[0] != '\\') 665169695Skan pid = win32_spawn (executable1, FALSE, argv, env, 666169695Skan dwCreationFlags, si, pi); 667169695Skan else 668169695Skan { 669169695Skan const char *newex = mingw_rootify (executable1); 670169695Skan *avhere = newex; 671169695Skan pid = win32_spawn (newex, FALSE, argv, env, 672169695Skan dwCreationFlags, si, pi); 673169695Skan if (executable1 != newex) 674169695Skan free ((char *) newex); 675169695Skan if (pid < 0) 676169695Skan { 677169695Skan newex = msys_rootify (executable1); 678169695Skan if (newex != executable1) 679169695Skan { 680169695Skan *avhere = newex; 681169695Skan pid = win32_spawn (newex, FALSE, argv, env, 682169695Skan dwCreationFlags, si, pi); 683169695Skan free ((char *) newex); 684169695Skan } 685169695Skan } 686169695Skan } 687169695Skan#endif 688169695Skan } 689169695Skan } 690169695Skan } 691169695Skan if (pid < 0) 692169695Skan errno = save_errno; 693169695Skan return pid; 694169695Skan} 695169695Skan 696169695Skan/* Execute a child. */ 697169695Skan 698169695Skanstatic long 699169695Skanpex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags, 700169695Skan const char *executable, char * const * argv, 701169695Skan char* const* env, 702169695Skan int in, int out, int errdes, 703169695Skan int toclose ATTRIBUTE_UNUSED, 704169695Skan const char **errmsg, 705169695Skan int *err) 706169695Skan{ 707169695Skan long pid; 708169695Skan HANDLE stdin_handle; 709169695Skan HANDLE stdout_handle; 710169695Skan HANDLE stderr_handle; 711169695Skan DWORD dwCreationFlags; 712169695Skan OSVERSIONINFO version_info; 713169695Skan STARTUPINFO si; 714169695Skan PROCESS_INFORMATION pi; 715169695Skan 716169695Skan stdin_handle = INVALID_HANDLE_VALUE; 717169695Skan stdout_handle = INVALID_HANDLE_VALUE; 718169695Skan stderr_handle = INVALID_HANDLE_VALUE; 719169695Skan 720169695Skan stdin_handle = (HANDLE) _get_osfhandle (in); 721169695Skan stdout_handle = (HANDLE) _get_osfhandle (out); 722169695Skan if (!(flags & PEX_STDERR_TO_STDOUT)) 723169695Skan stderr_handle = (HANDLE) _get_osfhandle (errdes); 724169695Skan else 725169695Skan stderr_handle = stdout_handle; 726169695Skan 727169695Skan /* Determine the version of Windows we are running on. */ 728169695Skan version_info.dwOSVersionInfoSize = sizeof (version_info); 729169695Skan GetVersionEx (&version_info); 730169695Skan if (version_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) 731169695Skan /* On Windows 95/98/ME the CREATE_NO_WINDOW flag is not 732169695Skan supported, so we cannot avoid creating a console window. */ 733169695Skan dwCreationFlags = 0; 734169695Skan else 735169695Skan { 736169695Skan HANDLE conout_handle; 737169695Skan 738169695Skan /* Determine whether or not we have an associated console. */ 739169695Skan conout_handle = CreateFile("CONOUT$", 740169695Skan GENERIC_WRITE, 741169695Skan FILE_SHARE_WRITE, 742169695Skan /*lpSecurityAttributes=*/NULL, 743169695Skan OPEN_EXISTING, 744169695Skan FILE_ATTRIBUTE_NORMAL, 745169695Skan /*hTemplateFile=*/NULL); 746169695Skan if (conout_handle == INVALID_HANDLE_VALUE) 747169695Skan /* There is no console associated with this process. Since 748169695Skan the child is a console process, the OS would normally 749169695Skan create a new console Window for the child. Since we'll be 750169695Skan redirecting the child's standard streams, we do not need 751169695Skan the console window. */ 752169695Skan dwCreationFlags = CREATE_NO_WINDOW; 753169695Skan else 754169695Skan { 755169695Skan /* There is a console associated with the process, so the OS 756169695Skan will not create a new console. And, if we use 757169695Skan CREATE_NO_WINDOW in this situation, the child will have 758169695Skan no associated console. Therefore, if the child's 759169695Skan standard streams are connected to the console, the output 760169695Skan will be discarded. */ 761169695Skan CloseHandle(conout_handle); 762169695Skan dwCreationFlags = 0; 763169695Skan } 764169695Skan } 765169695Skan 766169695Skan /* Since the child will be a console process, it will, by default, 767169695Skan connect standard input/output to its console. However, we want 768169695Skan the child to use the handles specifically designated above. In 769169695Skan addition, if there is no console (such as when we are running in 770169695Skan a Cygwin X window), then we must redirect the child's 771169695Skan input/output, as there is no console for the child to use. */ 772169695Skan memset (&si, 0, sizeof (si)); 773169695Skan si.cb = sizeof (si); 774169695Skan si.dwFlags = STARTF_USESTDHANDLES; 775169695Skan si.hStdInput = stdin_handle; 776169695Skan si.hStdOutput = stdout_handle; 777169695Skan si.hStdError = stderr_handle; 778169695Skan 779169695Skan /* Create the child process. */ 780169695Skan pid = win32_spawn (executable, (flags & PEX_SEARCH) != 0, 781169695Skan argv, env, dwCreationFlags, &si, &pi); 782169695Skan if (pid == -1) 783169695Skan pid = spawn_script (executable, argv, env, dwCreationFlags, 784169695Skan &si, &pi); 785169695Skan if (pid == -1) 786169695Skan { 787169695Skan *err = ENOENT; 788169695Skan *errmsg = "CreateProcess"; 789169695Skan } 790169695Skan 791169695Skan /* Close the standard output and standard error handles in the 792169695Skan parent. */ 793169695Skan if (out != STDOUT_FILENO) 794169695Skan obj->funcs->close (obj, out); 795169695Skan if (errdes != STDERR_FILENO) 796169695Skan obj->funcs->close (obj, errdes); 797169695Skan 798169695Skan return pid; 799169695Skan} 800169695Skan 801169695Skan/* Wait for a child process to complete. MS CRTDLL doesn't return 802169695Skan enough information in status to decide if the child exited due to a 803169695Skan signal or not, rather it simply returns an integer with the exit 804169695Skan code of the child; eg., if the child exited with an abort() call 805169695Skan and didn't have a handler for SIGABRT, it simply returns with 806169695Skan status == 3. We fix the status code to conform to the usual WIF* 807169695Skan macros. Note that WIFSIGNALED will never be true under CRTDLL. */ 808169695Skan 809169695Skanstatic int 810169695Skanpex_win32_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, long pid, 811169695Skan int *status, struct pex_time *time, int done ATTRIBUTE_UNUSED, 812169695Skan const char **errmsg, int *err) 813169695Skan{ 814169695Skan DWORD termstat; 815169695Skan HANDLE h; 816169695Skan 817169695Skan if (time != NULL) 818169695Skan memset (time, 0, sizeof *time); 819169695Skan 820169695Skan h = (HANDLE) pid; 821169695Skan 822169695Skan /* FIXME: If done is non-zero, we should probably try to kill the 823169695Skan process. */ 824169695Skan if (WaitForSingleObject (h, INFINITE) != WAIT_OBJECT_0) 825169695Skan { 826169695Skan CloseHandle (h); 827169695Skan *err = ECHILD; 828169695Skan *errmsg = "WaitForSingleObject"; 829169695Skan return -1; 830169695Skan } 831169695Skan 832169695Skan GetExitCodeProcess (h, &termstat); 833169695Skan CloseHandle (h); 834169695Skan 835169695Skan /* A value of 3 indicates that the child caught a signal, but not 836169695Skan which one. Since only SIGABRT, SIGFPE and SIGINT do anything, we 837169695Skan report SIGABRT. */ 838169695Skan if (termstat == 3) 839169695Skan *status = SIGABRT; 840169695Skan else 841169695Skan *status = (termstat & 0xff) << 8; 842169695Skan 843169695Skan return 0; 844169695Skan} 845169695Skan 846169695Skan/* Create a pipe. */ 847169695Skan 848169695Skanstatic int 849169695Skanpex_win32_pipe (struct pex_obj *obj ATTRIBUTE_UNUSED, int *p, 850169695Skan int binary) 851169695Skan{ 852169695Skan return _pipe (p, 256, binary ? _O_BINARY : _O_TEXT); 853169695Skan} 854169695Skan 855169695Skan/* Get a FILE pointer to read from a file descriptor. */ 856169695Skan 857169695Skanstatic FILE * 858169695Skanpex_win32_fdopenr (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd, 859169695Skan int binary) 860169695Skan{ 861169695Skan return fdopen (fd, binary ? "rb" : "r"); 862169695Skan} 863169695Skan 864169695Skanstatic FILE * 865169695Skanpex_win32_fdopenw (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd, 866169695Skan int binary) 867169695Skan{ 868169695Skan HANDLE h = (HANDLE) _get_osfhandle (fd); 869169695Skan if (h == INVALID_HANDLE_VALUE) 870169695Skan return NULL; 871169695Skan if (! SetHandleInformation (h, HANDLE_FLAG_INHERIT, 0)) 872169695Skan return NULL; 873169695Skan return fdopen (fd, binary ? "wb" : "w"); 874169695Skan} 875169695Skan 876169695Skan#ifdef MAIN 877169695Skan#include <stdio.h> 878169695Skan 879169695Skanint 880169695Skanmain (int argc ATTRIBUTE_UNUSED, char **argv) 881169695Skan{ 882169695Skan char const *errmsg; 883169695Skan int err; 884169695Skan argv++; 885169695Skan printf ("%ld\n", pex_win32_exec_child (NULL, PEX_SEARCH, argv[0], argv, NULL, 0, 0, 1, 2, &errmsg, &err)); 886169695Skan exit (0); 887169695Skan} 888169695Skan#endif 889