sh-quote, execute, spawn-pipe, etc.: Make better use of 'const'.
[gnulib.git] / lib / windows-spawn.c
blob88a6b4dba416ec2072fdcdb2d8aeb6358d589408
1 /* Auxiliary functions for the creation of subprocesses. Native Windows API.
2 Copyright (C) 2001, 2003-2020 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 <https://www.gnu.org/licenses/>. */
18 #include <config.h>
20 /* Specification. */
21 #include "windows-spawn.h"
23 /* Get declarations of the native Windows API functions. */
24 #define WIN32_LEAN_AND_MEAN
25 #include <windows.h>
27 #include <stdbool.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <errno.h>
33 /* Get _get_osfhandle(). */
34 #if GNULIB_MSVC_NOTHROW
35 # include "msvc-nothrow.h"
36 #else
37 # include <io.h>
38 #endif
39 #include <process.h>
41 #include "findprog.h"
43 /* Don't assume that UNICODE is not defined. */
44 #undef STARTUPINFO
45 #define STARTUPINFO STARTUPINFOA
46 #undef CreateProcess
47 #define CreateProcess CreateProcessA
49 #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*?"
50 #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"
52 /* Returns the length of a quoted argument string. */
53 static size_t
54 quoted_arg_length (const char *string)
56 bool quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
57 size_t length;
58 unsigned int backslashes;
59 const char *s;
61 length = 0;
62 backslashes = 0;
63 if (quote_around)
64 length++;
65 for (s = string; *s != '\0'; s++)
67 char c = *s;
68 if (c == '"')
69 length += backslashes + 1;
70 length++;
71 if (c == '\\')
72 backslashes++;
73 else
74 backslashes = 0;
76 if (quote_around)
77 length += backslashes + 1;
79 return length;
82 /* Produces a quoted argument string.
83 Stores exactly quoted_arg_length (STRING) + 1 bytes, including the final
84 NUL byte, at MEM.
85 Returns a pointer past the stored quoted argument string. */
86 static char *
87 quoted_arg_string (const char *string, char *mem)
89 bool quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
90 char *p;
91 unsigned int backslashes;
92 const char *s;
94 p = mem;
95 backslashes = 0;
96 if (quote_around)
97 *p++ = '"';
98 for (s = string; *s != '\0'; s++)
100 char c = *s;
101 if (c == '"')
103 unsigned int j;
104 for (j = backslashes + 1; j > 0; j--)
105 *p++ = '\\';
107 *p++ = c;
108 if (c == '\\')
109 backslashes++;
110 else
111 backslashes = 0;
113 if (quote_around)
115 unsigned int j;
116 for (j = backslashes; j > 0; j--)
117 *p++ = '\\';
118 *p++ = '"';
120 *p++ = '\0';
122 return p;
125 const char **
126 prepare_spawn (const char * const *argv, char **mem_to_free)
128 size_t argc;
129 const char **new_argv;
130 size_t i;
132 /* Count number of arguments. */
133 for (argc = 0; argv[argc] != NULL; argc++)
136 /* Allocate new argument vector. */
137 new_argv = (const char **) malloc ((1 + argc + 1) * sizeof (const char *));
139 /* Add an element upfront that can be used when argv[0] turns out to be a
140 script, not a program.
141 On Unix, this would be "/bin/sh". On native Windows, "sh" is actually
142 "sh.exe". We have to omit the directory part and rely on the search in
143 PATH, because the mingw "mount points" are not visible inside Windows
144 CreateProcess(). */
145 new_argv[0] = "sh.exe";
147 /* Put quoted arguments into the new argument vector. */
148 size_t needed_size = 0;
149 for (i = 0; i < argc; i++)
151 const char *string = argv[i];
152 size_t length;
154 if (string[0] == '\0')
155 length = strlen ("\"\"");
156 else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
157 length = quoted_arg_length (string);
158 else
159 length = strlen (string);
160 needed_size += length + 1;
163 char *mem;
164 if (needed_size == 0)
165 mem = NULL;
166 else
168 mem = (char *) malloc (needed_size);
169 if (mem == NULL)
171 /* Memory allocation failure. */
172 free (new_argv);
173 errno = ENOMEM;
174 return NULL;
177 *mem_to_free = mem;
179 for (i = 0; i < argc; i++)
181 const char *string = argv[i];
183 new_argv[1 + i] = mem;
184 if (string[0] == '\0')
186 size_t length = strlen ("\"\"");
187 memcpy (mem, "\"\"", length + 1);
188 mem += length + 1;
190 else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
192 mem = quoted_arg_string (string, mem);
194 else
196 size_t length = strlen (string);
197 memcpy (mem, string, length + 1);
198 mem += length + 1;
201 new_argv[1 + argc] = NULL;
203 return new_argv;
206 intptr_t
207 spawnpvech (int mode,
208 const char *progname, const char * const *argv,
209 const char * const *envp,
210 const char *currdir,
211 HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle)
213 /* Validate the arguments. */
214 if (!(mode == P_WAIT
215 || mode == P_NOWAIT
216 || mode == P_DETACH
217 || mode == P_OVERLAY)
218 || progname == NULL || argv == NULL)
220 errno = EINVAL;
221 return -1;
224 /* Implement the 'p' letter: search for PROGNAME in getenv ("PATH"). */
225 const char *resolved_progname =
226 find_in_given_path (progname, getenv ("PATH"), false);
227 if (resolved_progname == NULL)
228 return -1;
230 /* Compose the command.
231 Just concatenate the argv[] strings, separated by spaces. */
232 char *command;
234 /* Determine the size of the needed block of memory. */
235 size_t total_size = 0;
236 const char * const *ap;
237 const char *p;
238 for (ap = argv; (p = *ap) != NULL; ap++)
239 total_size += strlen (p) + 1;
240 size_t command_size = (total_size > 0 ? total_size : 1);
241 command = (char *) malloc (command_size);
242 if (command == NULL)
243 goto out_of_memory_1;
244 if (total_size > 0)
246 char *cp = command;
247 for (ap = argv; (p = *ap) != NULL; ap++)
249 size_t size = strlen (p) + 1;
250 memcpy (cp, p, size - 1);
251 cp += size;
252 cp[-1] = ' ';
254 cp[-1] = '\0';
256 else
257 *command = '\0';
260 /* Copy *ENVP into a contiguous block of memory. */
261 char *envblock;
262 if (envp == NULL)
263 envblock = NULL;
264 else
265 retry:
267 /* Guess the size of the needed block of memory.
268 The guess will be exact if other threads don't make modifications. */
269 size_t total_size = 0;
270 const char * const *ep;
271 const char *p;
272 for (ep = envp; (p = *ep) != NULL; ep++)
273 total_size += strlen (p) + 1;
274 size_t envblock_size = total_size;
275 envblock = (char *) malloc (envblock_size + 1);
276 if (envblock == NULL)
277 goto out_of_memory_2;
278 size_t envblock_used = 0;
279 for (ep = envp; (p = *ep) != NULL; ep++)
281 size_t size = strlen (p) + 1;
282 if (envblock_used + size > envblock_size)
284 /* Other threads did modifications. Need more memory. */
285 envblock_size += envblock_size / 2;
286 if (envblock_used + size > envblock_size)
287 envblock_size = envblock_used + size;
289 char *new_envblock = (char *) realloc (envblock, envblock_size + 1);
290 if (new_envblock == NULL)
291 goto out_of_memory_3;
292 envblock = new_envblock;
294 memcpy (envblock + envblock_used, p, size);
295 envblock_used += size;
296 if (envblock[envblock_used - 1] != '\0')
298 /* Other threads did modifications. Restart. */
299 free (envblock);
300 goto retry;
303 envblock[envblock_used] = '\0';
306 /* CreateProcess
307 <https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa> */
308 /* Regarding handle inheritance, see
309 <https://docs.microsoft.com/en-us/windows/win32/sysinfo/handle-inheritance> */
310 /* <https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags> */
311 DWORD flags = (mode == P_DETACH ? DETACHED_PROCESS : 0);
312 /* STARTUPINFO
313 <https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa> */
314 STARTUPINFO sinfo;
315 sinfo.cb = sizeof (STARTUPINFO);
316 sinfo.lpReserved = NULL;
317 sinfo.lpDesktop = NULL;
318 sinfo.lpTitle = NULL;
319 sinfo.dwFlags = STARTF_USESTDHANDLES;
320 sinfo.hStdInput = stdin_handle;
321 sinfo.hStdOutput = stdout_handle;
322 sinfo.hStdError = stderr_handle;
324 char *hblock = NULL;
325 #if 0
326 sinfo.cbReserved2 = 0;
327 sinfo.lpReserved2 = NULL;
328 #else
329 /* On newer versions of Windows, more file descriptors / handles than the
330 first three can be passed.
331 The format is as follows: Let N be an exclusive upper bound for the file
332 descriptors to be passed. Two arrays are constructed in memory:
333 - flags[0..N-1], of element type 'unsigned char',
334 - handles[0..N-1], of element type 'HANDLE' or 'intptr_t'.
335 For used entries, handles[i] is the handle, and flags[i] is a set of flags,
336 a combination of:
337 1 for open file descriptors,
338 64 for handles of type FILE_TYPE_CHAR,
339 8 for handles of type FILE_TYPE_PIPE.
340 For unused entries - this includes the first three, since they are already
341 passed above -, handles[i] is INVALID_HANDLE_VALUE and flags[i] is zero.
342 lpReserved2 now is a pointer to the concatenation (without padding) of:
343 - an 'unsigned int' whose value is N,
344 - the contents of the flags[0..N-1] array,
345 - the contents of the handles[0..N-1] array.
346 cbReserved2 is the size (in bytes) of the object at lpReserved2. */
348 /* _getmaxstdio
349 <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/getmaxstdio>
350 Default value is 512. */
351 unsigned int fdmax;
352 for (fdmax = _getmaxstdio (); fdmax > 0; fdmax--)
354 unsigned int fd = fdmax - 1;
355 /* _get_osfhandle
356 <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle> */
357 HANDLE handle = (HANDLE) _get_osfhandle (fd);
358 if (handle != INVALID_HANDLE_VALUE)
360 DWORD hflags;
361 /* GetHandleInformation
362 <https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-gethandleinformation> */
363 if (GetHandleInformation (handle, &hflags))
365 if ((hflags & HANDLE_FLAG_INHERIT) != 0)
366 /* fd denotes an inheritable descriptor. */
367 break;
371 if (fdmax > 0)
373 sinfo.cbReserved2 =
374 sizeof (unsigned int)
375 + fdmax * sizeof (unsigned char)
376 + fdmax * sizeof (HANDLE);
377 /* Add some padding, so that we can work with a properly HANDLE array. */
378 hblock = (char *) malloc (sinfo.cbReserved2 + (sizeof (HANDLE) - 1));
379 if (hblock == NULL)
380 goto out_of_memory_3;
381 * (unsigned int *) hblock = fdmax;
382 unsigned char *flags = (unsigned char *) (hblock + sizeof (unsigned int));
383 char *handles = (char *) (flags + fdmax);
384 HANDLE *handles_aligned =
385 (HANDLE *) (((uintptr_t) handles + (sizeof (HANDLE) - 1))
386 & - (uintptr_t) sizeof (HANDLE));
388 unsigned int fd;
389 for (fd = 0; fd < fdmax; fd++)
391 flags[fd] = 0;
392 handles_aligned[fd] = INVALID_HANDLE_VALUE;
393 /* The first three are already passed above. */
394 if (fd >= 3)
396 /* _get_osfhandle
397 <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle> */
398 HANDLE handle = (HANDLE) _get_osfhandle (fd);
399 if (handle != INVALID_HANDLE_VALUE)
401 DWORD hflags;
402 /* GetHandleInformation
403 <https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-gethandleinformation> */
404 if (GetHandleInformation (handle, &hflags))
406 if ((hflags & HANDLE_FLAG_INHERIT) != 0)
408 /* fd denotes an inheritable descriptor. */
409 /* On Microsoft Windows, it would be sufficient to
410 set flags[fd] = 1. But on ReactOS or Wine,
411 adding the bit that indicates the handle type
412 may be necessary. So, just do it everywhere. */
413 switch (GetFileType (handle))
415 case FILE_TYPE_CHAR:
416 flags[fd] = 64 | 1;
417 break;
418 case FILE_TYPE_PIPE:
419 flags[fd] = 8 | 1;
420 break;
421 default:
422 flags[fd] = 1;
423 break;
425 handles_aligned[fd] = handle;
432 if (handles != (char *) handles_aligned)
433 memmove (handles, (char *) handles_aligned, fdmax * sizeof (HANDLE));
434 sinfo.lpReserved2 = (BYTE *) hblock;
436 else
438 sinfo.cbReserved2 = 0;
439 sinfo.lpReserved2 = NULL;
442 #endif
444 PROCESS_INFORMATION pinfo;
445 if (!CreateProcess (resolved_progname, command, NULL, NULL, TRUE,
446 flags, envblock, currdir, &sinfo, &pinfo))
448 DWORD error = GetLastError ();
450 if (hblock != NULL)
451 free (hblock);
452 if (envblock != NULL)
453 free (envblock);
454 free (command);
455 if (resolved_progname != progname)
456 free ((char *) resolved_progname);
458 /* Some of these errors probably cannot happen. But who knows... */
459 switch (error)
461 case ERROR_FILE_NOT_FOUND:
462 case ERROR_PATH_NOT_FOUND:
463 case ERROR_BAD_PATHNAME:
464 case ERROR_BAD_NET_NAME:
465 case ERROR_INVALID_NAME:
466 case ERROR_DIRECTORY:
467 errno = ENOENT;
468 break;
470 case ERROR_ACCESS_DENIED:
471 case ERROR_SHARING_VIOLATION:
472 errno = EACCES;
473 break;
475 case ERROR_OUTOFMEMORY:
476 errno = ENOMEM;
477 break;
479 case ERROR_BUFFER_OVERFLOW:
480 case ERROR_FILENAME_EXCED_RANGE:
481 errno = ENAMETOOLONG;
482 break;
484 default:
485 errno = EINVAL;
486 break;
489 return -1;
492 if (pinfo.hThread)
493 CloseHandle (pinfo.hThread);
494 if (hblock != NULL)
495 free (hblock);
496 if (envblock != NULL)
497 free (envblock);
498 free (command);
499 if (resolved_progname != progname)
500 free ((char *) resolved_progname);
502 switch (mode)
504 case P_WAIT:
506 /* Wait until it terminates. Then get its exit status code. */
507 switch (WaitForSingleObject (pinfo.hProcess, INFINITE))
509 case WAIT_OBJECT_0:
510 break;
511 case WAIT_FAILED:
512 errno = ECHILD;
513 return -1;
514 default:
515 abort ();
518 DWORD exit_code;
519 if (!GetExitCodeProcess (pinfo.hProcess, &exit_code))
521 errno = ECHILD;
522 return -1;
524 CloseHandle (pinfo.hProcess);
525 return exit_code;
528 case P_NOWAIT:
529 /* Return pinfo.hProcess, not pinfo.dwProcessId. */
530 return (intptr_t) pinfo.hProcess;
532 case P_DETACH:
533 case P_OVERLAY:
534 CloseHandle (pinfo.hProcess);
535 return 0;
537 default:
538 /* Already checked above. */
539 abort ();
542 /*NOTREACHED*/
543 #if 0
544 out_of_memory_4:
545 if (hblock != NULL)
546 free (hblock);
547 #endif
548 out_of_memory_3:
549 if (envblock != NULL)
550 free (envblock);
551 out_of_memory_2:
552 free (command);
553 out_of_memory_1:
554 if (resolved_progname != progname)
555 free ((char *) resolved_progname);
556 errno = ENOMEM;
557 return -1;