1 /* Auxiliary functions for the creation of subprocesses. Native Woe32 API.
2 Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2003.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 /* Get declarations of the Win32 API functions. */
19 #define WIN32_LEAN_AND_MEAN
22 /* Get _get_osfhandle() and _open_osfhandle(). */
31 /* Duplicates a file handle, making the copy uninheritable. */
33 dup_noinherit (int fd)
35 HANDLE curr_process = GetCurrentProcess ();
36 HANDLE old_handle = (HANDLE) _get_osfhandle (fd);
40 if (!DuplicateHandle (curr_process, /* SourceProcessHandle */
41 old_handle, /* SourceHandle */
42 curr_process, /* TargetProcessHandle */
43 (PHANDLE) &new_handle, /* TargetHandle */
44 (DWORD) 0, /* DesiredAccess */
45 FALSE, /* InheritHandle */
46 DUPLICATE_SAME_ACCESS)) /* Options */
47 error (EXIT_FAILURE, 0, _("DuplicateHandle failed with error code 0x%08x"),
50 nfd = _open_osfhandle ((long) new_handle, O_BINARY);
52 error (EXIT_FAILURE, errno, _("_open_osfhandle failed"));
57 /* Prepares an argument vector before calling spawn().
58 Note that spawn() does not by itself call the command interpreter
59 (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
60 ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
62 v.dwPlatformId == VER_PLATFORM_WIN32_NT;
63 }) ? "cmd.exe" : "command.com").
64 Instead it simply concatenates the arguments, separated by ' ', and calls
65 CreateProcess(). We must quote the arguments since Win32 CreateProcess()
66 interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
68 - Space and tab are interpreted as delimiters. They are not treated as
69 delimiters if they are surrounded by double quotes: "...".
70 - Unescaped double quotes are removed from the input. Their only effect is
71 that within double quotes, space and tab are treated like normal
73 - Backslashes not followed by double quotes are not special.
74 - But 2*n+1 backslashes followed by a double quote become
75 n backslashes followed by a double quote (n >= 0):
80 #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"
81 #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"
83 prepare_spawn (char **argv)
89 /* Count number of arguments. */
90 for (argc = 0; argv[argc] != NULL; argc++)
93 /* Allocate new argument vector. */
94 new_argv = XNMALLOC (argc + 1, char *);
96 /* Put quoted arguments into the new argument vector. */
97 for (i = 0; i < argc; i++)
99 const char *string = argv[i];
101 if (string[0] == '\0')
102 new_argv[i] = xstrdup ("\"\"");
103 else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
105 bool quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
107 unsigned int backslashes;
116 for (s = string; *s != '\0'; s++)
120 length += backslashes + 1;
128 length += backslashes + 1;
130 quoted_string = (char *) xmalloc (length + 1);
136 for (s = string; *s != '\0'; s++)
142 for (j = backslashes + 1; j > 0; j--)
154 for (j = backslashes; j > 0; j--)
160 new_argv[i] = quoted_string;
163 new_argv[i] = (char *) string;
165 new_argv[argc] = NULL;