X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fw32spawn.h;h=3b5c08afcd4153e386c441531a9e6438698eabd5;hb=5191b3546cfb6c163228c23f214e325ddf60d46f;hp=9ebf5bc49c9c913d59f4a1a3e05693197c0fe2e7;hpb=a7dd7898b03b95173995e1b69733fd0e91aa04cf;p=gnulib.git diff --git a/lib/w32spawn.h b/lib/w32spawn.h index 9ebf5bc49..3b5c08afc 100644 --- a/lib/w32spawn.h +++ b/lib/w32spawn.h @@ -1,5 +1,5 @@ -/* Auxiliary functions for the creation of subprocesses. Native Woe32 API. - Copyright (C) 2003, 2006-2008 Free Software Foundation, Inc. +/* Auxiliary functions for the creation of subprocesses. Native Windows API. + Copyright (C) 2001, 2003-2013 Free Software Foundation, Inc. Written by Bruno Haible , 2003. This program is free software: you can redistribute it and/or modify @@ -15,43 +15,82 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -/* Get declarations of the Win32 API functions. */ +/* Get declarations of the native Windows API functions. */ #define WIN32_LEAN_AND_MEAN #include -/* Get _get_osfhandle() and _open_osfhandle(). */ +/* Get _open_osfhandle(). */ #include #include #include +#include #include +/* Get _get_osfhandle(). */ +#include "msvc-nothrow.h" + +#include "cloexec.h" #include "xalloc.h" -/* Duplicates a file handle, making the copy uninheritable. */ +/* Duplicates a file handle, making the copy uninheritable. + Returns -1 for a file handle that is equivalent to closed. */ static int dup_noinherit (int fd) { - HANDLE curr_process = GetCurrentProcess (); - HANDLE old_handle = (HANDLE) _get_osfhandle (fd); - HANDLE new_handle; - int nfd; - - if (!DuplicateHandle (curr_process, /* SourceProcessHandle */ - old_handle, /* SourceHandle */ - curr_process, /* TargetProcessHandle */ - (PHANDLE) &new_handle, /* TargetHandle */ - (DWORD) 0, /* DesiredAccess */ - FALSE, /* InheritHandle */ - DUPLICATE_SAME_ACCESS)) /* Options */ - error (EXIT_FAILURE, 0, _("DuplicateHandle failed with error code 0x%08x"), - GetLastError ()); - - nfd = _open_osfhandle ((long) new_handle, O_BINARY); - if (nfd < 0) + fd = dup_cloexec (fd); + if (fd < 0 && errno == EMFILE) error (EXIT_FAILURE, errno, _("_open_osfhandle failed")); - return nfd; + return fd; +} + +/* Returns a file descriptor equivalent to FD, except that the resulting file + descriptor is none of STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO. + FD must be open and non-inheritable. The result will be non-inheritable as + well. + If FD < 0, FD itself is returned. */ +static int +fd_safer_noinherit (int fd) +{ + if (STDIN_FILENO <= fd && fd <= STDERR_FILENO) + { + /* The recursion depth is at most 3. */ + int nfd = fd_safer_noinherit (dup_noinherit (fd)); + int saved_errno = errno; + close (fd); + errno = saved_errno; + return nfd; + } + return fd; +} + +/* Duplicates a file handle, making the copy uninheritable and ensuring the + result is none of STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO. + Returns -1 for a file handle that is equivalent to closed. */ +static int +dup_safer_noinherit (int fd) +{ + return fd_safer_noinherit (dup_noinherit (fd)); +} + +/* Undoes the effect of TEMPFD = dup_safer_noinherit (ORIGFD); */ +static void +undup_safer_noinherit (int tempfd, int origfd) +{ + if (tempfd >= 0) + { + if (dup2 (tempfd, origfd) < 0) + error (EXIT_FAILURE, errno, _("cannot restore fd %d: dup2 failed"), + origfd); + close (tempfd); + } + else + { + /* origfd was closed or open to no handle at all. Set it to a closed + state. This is (nearly) equivalent to the original state. */ + close (origfd); + } } /* Prepares an argument vector before calling spawn(). @@ -62,7 +101,7 @@ dup_noinherit (int fd) v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls - CreateProcess(). We must quote the arguments since Win32 CreateProcess() + CreateProcess(). We must quote the arguments since Windows CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as @@ -76,8 +115,15 @@ dup_noinherit (int fd) \" -> " \\\" -> \" \\\\\" -> \\" + - '*', '?' characters may get expanded through wildcard expansion in the + callee: By default, in the callee, the initialization code before main() + takes the result of GetCommandLine(), wildcard-expands it, and passes it + to main(). The exceptions to this rule are: + - programs that inspect GetCommandLine() and ignore argv, + - mingw programs that have a global variable 'int _CRT_glob = 0;', + - Cygwin programs, when invoked from a Cygwin program. */ -#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037*?" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" static char ** prepare_spawn (char **argv) @@ -97,7 +143,7 @@ prepare_spawn (char **argv) script, not a program. On Unix, this would be "/bin/sh". On native Windows, "sh" is actually "sh.exe". We have to omit the directory part and rely on the search in - PATH, because the mingw "mount points" are not visible inside Win32 + PATH, because the mingw "mount points" are not visible inside Windows CreateProcess(). */ *new_argv++ = "sh.exe"; @@ -107,68 +153,68 @@ prepare_spawn (char **argv) const char *string = argv[i]; if (string[0] == '\0') - new_argv[i] = xstrdup ("\"\""); + new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) - { - bool quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); - size_t length; - unsigned int backslashes; - const char *s; - char *quoted_string; - char *p; - - length = 0; - backslashes = 0; - if (quote_around) - length++; - for (s = string; *s != '\0'; s++) - { - char c = *s; - if (c == '"') - length += backslashes + 1; - length++; - if (c == '\\') - backslashes++; - else - backslashes = 0; - } - if (quote_around) - length += backslashes + 1; - - quoted_string = (char *) xmalloc (length + 1); - - p = quoted_string; - backslashes = 0; - if (quote_around) - *p++ = '"'; - for (s = string; *s != '\0'; s++) - { - char c = *s; - if (c == '"') - { - unsigned int j; - for (j = backslashes + 1; j > 0; j--) - *p++ = '\\'; - } - *p++ = c; - if (c == '\\') - backslashes++; - else - backslashes = 0; - } - if (quote_around) - { - unsigned int j; - for (j = backslashes; j > 0; j--) - *p++ = '\\'; - *p++ = '"'; - } - *p = '\0'; - - new_argv[i] = quoted_string; - } + { + bool quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = (char *) xmalloc (length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } else - new_argv[i] = (char *) string; + new_argv[i] = (char *) string; } new_argv[argc] = NULL;