X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=libiberty%2Fpex-win32.c;h=331067b5078347912bc3828186629a52244aa1b9;hb=0fc2a808cbf5302016535367191bb8cd0900f332;hp=5897866347d7b1b08ac7d1e62a44349387a2d558;hpb=bd8aab1c2944a603af1182db1d81cfbd832d162a;p=deliverable%2Fbinutils-gdb.git diff --git a/libiberty/pex-win32.c b/libiberty/pex-win32.c index 5897866347..331067b507 100644 --- a/libiberty/pex-win32.c +++ b/libiberty/pex-win32.c @@ -1,7 +1,6 @@ /* Utilities to execute a program in a subprocess (possibly linked by pipes with other subprocesses), and wait for it. Generic Win32 specialization. - Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. + Copyright (C) 1996-2020 Free Software Foundation, Inc. This file is part of the libiberty library. Libiberty is free software; you can redistribute it and/or @@ -78,13 +77,13 @@ backslashify (char *s) } static int pex_win32_open_read (struct pex_obj *, const char *, int); -static int pex_win32_open_write (struct pex_obj *, const char *, int); +static int pex_win32_open_write (struct pex_obj *, const char *, int, int); static pid_t pex_win32_exec_child (struct pex_obj *, int, const char *, char * const *, char * const *, int, int, int, int, const char **, int *); static int pex_win32_close (struct pex_obj *, int); -static int pex_win32_wait (struct pex_obj *, pid_t, int *, +static pid_t pex_win32_wait (struct pex_obj *, pid_t, int *, struct pex_time *, int, const char **, int *); static int pex_win32_pipe (struct pex_obj *, int *, int); static FILE *pex_win32_fdopenr (struct pex_obj *, int, int); @@ -126,10 +125,12 @@ pex_win32_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, static int pex_win32_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, - int binary) + int binary, int append) { /* Note that we can't use O_EXCL here because gcc may have already created the temporary file via make_temp_file. */ + if (append) + return -1; return _open (name, (_O_WRONLY | _O_CREAT | _O_TRUNC | (binary ? _O_BINARY : _O_TEXT)), @@ -210,10 +211,8 @@ mingw_rootify (const char *executable) if (!namebuf || !foundbuf) { RegCloseKey (hKey); - if (namebuf) - free (namebuf); - if (foundbuf) - free (foundbuf); + free (namebuf); + free (foundbuf); return executable; } @@ -315,8 +314,7 @@ msys_rootify (const char *executable) return tack_on_executable (buf, executable); /* failed */ - if (buf) - free (buf); + free (buf); return executable; } #endif @@ -343,17 +341,25 @@ argv_to_cmdline (char *const *argv) char *p; size_t cmdline_len; int i, j, k; + int needs_quotes; cmdline_len = 0; for (i = 0; argv[i]; i++) { - /* We quote every last argument. This simplifies the problem; - we need only escape embedded double-quotes and immediately + /* We only quote arguments that contain spaces, \t or " characters to + prevent wasting 2 chars per argument of the CreateProcess 32k char + limit. We need only escape embedded double-quotes and immediately preceeding backslash characters. A sequence of backslach characters that is not follwed by a double quote character will not be escaped. */ + needs_quotes = 0; for (j = 0; argv[i][j]; j++) { + if (argv[i][j] == ' ' || argv[i][j] == '\t' || argv[i][j] == '"') + { + needs_quotes = 1; + } + if (argv[i][j] == '"') { /* Escape preceeding backslashes. */ @@ -363,18 +369,39 @@ argv_to_cmdline (char *const *argv) cmdline_len++; } } + if (j == 0) + needs_quotes = 1; /* Trailing backslashes also need to be escaped because they will be followed by the terminating quote. */ - for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--) - cmdline_len++; + if (needs_quotes) + { + for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--) + cmdline_len++; + } cmdline_len += j; - cmdline_len += 3; /* for leading and trailing quotes and space */ + /* for leading and trailing quotes and space */ + cmdline_len += needs_quotes * 2 + 1; } cmdline = XNEWVEC (char, cmdline_len); p = cmdline; for (i = 0; argv[i]; i++) { - *p++ = '"'; + needs_quotes = 0; + for (j = 0; argv[i][j]; j++) + { + if (argv[i][j] == ' ' || argv[i][j] == '\t' || argv[i][j] == '"') + { + needs_quotes = 1; + break; + } + } + if (j == 0) + needs_quotes = 1; + + if (needs_quotes) + { + *p++ = '"'; + } for (j = 0; argv[i][j]; j++) { if (argv[i][j] == '"') @@ -385,9 +412,12 @@ argv_to_cmdline (char *const *argv) } *p++ = argv[i][j]; } - for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--) - *p++ = '\\'; - *p++ = '"'; + if (needs_quotes) + { + for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--) + *p++ = '\\'; + *p++ = '"'; + } *p++ = ' '; } p[-1] = '\0'; @@ -607,8 +637,7 @@ win32_spawn (const char *executable, si, pi)) { - if (env_block) - free (env_block); + free (env_block); free (full_executable); @@ -618,18 +647,14 @@ win32_spawn (const char *executable, /* Clean up. */ CloseHandle (pi->hThread); free (full_executable); - if (env_block) - free (env_block); + free (env_block); return (pid_t) pi->hProcess; error: - if (env_block) - free (env_block); - if (cmdline) - free (cmdline); - if (full_executable) - free (full_executable); + free (env_block); + free (cmdline); + free (full_executable); return (pid_t) -1; } @@ -705,7 +730,7 @@ spawn_script (const char *executable, char *const *argv, dwCreationFlags, si, pi); if (executable1 != newex) free ((char *) newex); - if ((long) pid < 0) + if (pid == (pid_t) -1) { newex = msys_rootify (executable1); if (newex != executable1) @@ -722,7 +747,7 @@ spawn_script (const char *executable, char *const *argv, } } } - if ((long) pid < 0) + if (pid == (pid_t) -1) errno = save_errno; return pid; } @@ -746,6 +771,21 @@ pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags, OSVERSIONINFO version_info; STARTUPINFO si; PROCESS_INFORMATION pi; + int orig_out, orig_in, orig_err; + BOOL separate_stderr = !(flags & PEX_STDERR_TO_STDOUT); + + /* Ensure we have inheritable descriptors to pass to the child. */ + orig_in = in; + in = _dup (orig_in); + + orig_out = out; + out = _dup (orig_out); + + if (separate_stderr) + { + orig_err = errdes; + errdes = _dup (orig_err); + } stdin_handle = INVALID_HANDLE_VALUE; stdout_handle = INVALID_HANDLE_VALUE; @@ -753,7 +793,7 @@ pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags, stdin_handle = (HANDLE) _get_osfhandle (in); stdout_handle = (HANDLE) _get_osfhandle (out); - if (!(flags & PEX_STDERR_TO_STDOUT)) + if (separate_stderr) stderr_handle = (HANDLE) _get_osfhandle (errdes); else stderr_handle = stdout_handle; @@ -822,12 +862,29 @@ pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags, *errmsg = "CreateProcess"; } - /* Close the standard output and standard error handles in the - parent. */ - if (out != STDOUT_FILENO) - obj->funcs->close (obj, out); - if (errdes != STDERR_FILENO) - obj->funcs->close (obj, errdes); + /* If the child was created successfully, close the original file + descriptors. If the process creation fails, these are closed by + pex_run_in_environment instead. We must not close them twice as + that seems to cause a Windows exception. */ + + if (pid != (pid_t) -1) + { + if (orig_in != STDIN_FILENO) + _close (orig_in); + if (orig_out != STDOUT_FILENO) + _close (orig_out); + if (separate_stderr + && orig_err != STDERR_FILENO) + _close (orig_err); + } + + /* Close the standard input, standard output and standard error handles + in the parent. */ + + _close (in); + _close (out); + if (separate_stderr) + _close (errdes); return pid; } @@ -840,7 +897,7 @@ pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags, status == 3. We fix the status code to conform to the usual WIF* macros. Note that WIFSIGNALED will never be true under CRTDLL. */ -static int +static pid_t pex_win32_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid, int *status, struct pex_time *time, int done ATTRIBUTE_UNUSED, const char **errmsg, int *err) @@ -883,7 +940,7 @@ static int pex_win32_pipe (struct pex_obj *obj ATTRIBUTE_UNUSED, int *p, int binary) { - return _pipe (p, 256, binary ? _O_BINARY : _O_TEXT); + return _pipe (p, 256, (binary ? _O_BINARY : _O_TEXT) | _O_NOINHERIT); } /* Get a FILE pointer to read from a file descriptor. */ @@ -892,6 +949,11 @@ static FILE * pex_win32_fdopenr (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd, int binary) { + HANDLE h = (HANDLE) _get_osfhandle (fd); + if (h == INVALID_HANDLE_VALUE) + return NULL; + if (! SetHandleInformation (h, HANDLE_FLAG_INHERIT, 0)) + return NULL; return fdopen (fd, binary ? "rb" : "r"); }