-/* Auxiliary functions for the creation of subprocesses. Native Woe32 API.
- Copyright (C) 2001, 2003, 2004-2009 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 <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-/* Get declarations of the Win32 API functions. */
+/* Get declarations of the native Windows API functions. */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
-/* Get _get_osfhandle() and _open_osfhandle(). */
+/* Get _open_osfhandle(). */
#include <io.h>
#include <stdbool.h>
#include <unistd.h>
#include <errno.h>
+/* Get _get_osfhandle(). */
+#include "msvc-nothrow.h"
+
#include "cloexec.h"
#include "xalloc.h"
{
if (dup2 (tempfd, origfd) < 0)
error (EXIT_FAILURE, errno, _("cannot restore fd %d: dup2 failed"),
- origfd);
+ 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. */
+ state. This is (nearly) equivalent to the original state. */
close (origfd);
}
}
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
\" -> "
\\\" -> \"
\\\\\" -> \\"
+ - '*', '?' 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)
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";
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;