Sync usage with man page.
[netbsd-mini2440.git] / gnu / dist / gettext / gettext-tools / lib / w32spawn.h
blob18e64d7d5f5b64f13bb44a7e3c42e523f3bdc633
1 /* Auxiliary functions for the creation of subprocesses. Native Woe32 API.
2 Copyright (C) 2003 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 2, or (at your option)
8 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, write to the Free Software Foundation,
17 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19 /* Get declarations of the Win32 API functions. */
20 #define WIN32_LEAN_AND_MEAN
21 #include <windows.h>
23 /* Get _get_osfhandle() and _open_osfhandle(). */
24 #include <io.h>
26 #include <stdbool.h>
27 #include <errno.h>
29 #include "strpbrk.h"
30 #include "xalloc.h"
32 /* Duplicates a file handle, making the copy uninheritable. */
33 static int
34 dup_noinherit (int fd)
36 HANDLE curr_process = GetCurrentProcess ();
37 HANDLE old_handle = (HANDLE) _get_osfhandle (fd);
38 HANDLE new_handle;
39 int nfd;
41 if (!DuplicateHandle (curr_process, /* SourceProcessHandle */
42 old_handle, /* SourceHandle */
43 curr_process, /* TargetProcessHandle */
44 (PHANDLE) &new_handle, /* TargetHandle */
45 (DWORD) 0, /* DesiredAccess */
46 FALSE, /* InheritHandle */
47 DUPLICATE_SAME_ACCESS)) /* Options */
48 error (EXIT_FAILURE, 0, _("DuplicateHandle failed with error code 0x%08x"),
49 GetLastError ());
51 nfd = _open_osfhandle ((long) new_handle, O_BINARY);
52 if (nfd < 0)
53 error (EXIT_FAILURE, errno, _("_open_osfhandle failed"));
55 return nfd;
58 /* Prepares an argument vector before calling spawn().
59 Note that spawn() does not by itself call the command interpreter
60 (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
61 ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
62 GetVersionEx(&v);
63 v.dwPlatformId == VER_PLATFORM_WIN32_NT;
64 }) ? "cmd.exe" : "command.com").
65 Instead it simply concatenates the arguments, separated by ' ', and calls
66 CreateProcess(). We must quote the arguments since Win32 CreateProcess()
67 interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
68 special way:
69 - Space and tab are interpreted as delimiters. They are not treated as
70 delimiters if they are surrounded by double quotes: "...".
71 - Unescaped double quotes are removed from the input. Their only effect is
72 that within double quotes, space and tab are treated like normal
73 characters.
74 - Backslashes not followed by double quotes are not special.
75 - But 2*n+1 backslashes followed by a double quote become
76 n backslashes followed by a double quote (n >= 0):
77 \" -> "
78 \\\" -> \"
79 \\\\\" -> \\"
81 #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"
82 #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 static char **
84 prepare_spawn (char **argv)
86 size_t argc;
87 char **new_argv;
88 size_t i;
90 /* Count number of arguments. */
91 for (argc = 0; argv[argc] != NULL; argc++)
94 /* Allocate new argument vector. */
95 new_argv = (char **) xmalloc ((argc + 1) * sizeof (char *));
97 /* Put quoted arguments into the new argument vector. */
98 for (i = 0; i < argc; i++)
100 const char *string = argv[i];
102 if (string[0] == '\0')
103 new_argv[i] = xstrdup ("\"\"");
104 else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
106 bool quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
107 size_t length;
108 unsigned int backslashes;
109 const char *s;
110 char *quoted_string;
111 char *p;
113 length = 0;
114 backslashes = 0;
115 if (quote_around)
116 length++;
117 for (s = string; *s != '\0'; s++)
119 char c = *s;
120 if (c == '"')
121 length += backslashes + 1;
122 length++;
123 if (c == '\\')
124 backslashes++;
125 else
126 backslashes = 0;
128 if (quote_around)
129 length += backslashes + 1;
131 quoted_string = (char *) xmalloc (length + 1);
133 p = quoted_string;
134 backslashes = 0;
135 if (quote_around)
136 *p++ = '"';
137 for (s = string; *s != '\0'; s++)
139 char c = *s;
140 if (c == '"')
142 unsigned int j;
143 for (j = backslashes + 1; j > 0; j--)
144 *p++ = '\\';
146 *p++ = c;
147 if (c == '\\')
148 backslashes++;
149 else
150 backslashes = 0;
152 if (quote_around)
154 unsigned int j;
155 for (j = backslashes; j > 0; j--)
156 *p++ = '\\';
157 *p++ = '"';
159 *p = '\0';
161 new_argv[i] = quoted_string;
163 else
164 new_argv[i] = (char *) string;
166 new_argv[argc] = NULL;
168 return new_argv;