exp2l: Work around a NetBSD 10.0/i386 bug.
[gnulib.git] / lib / windows-spawn.c
blob203e3e873cdc8e4de2206ddfdf40f29943a22030
1 /* Auxiliary functions for the creation of subprocesses. Native Windows API.
2 Copyright (C) 2001, 2003-2024 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2003.
5 This file is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as
7 published by the Free Software Foundation; either version 2.1 of the
8 License, or (at your option) any later version.
10 This file 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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser 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 <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
32 /* Get _get_osfhandle(). */
33 #if GNULIB_MSVC_NOTHROW
34 # include "msvc-nothrow.h"
35 #else
36 # include <io.h>
37 #endif
38 #include <process.h>
40 #include "findprog.h"
42 /* Don't assume that UNICODE is not defined. */
43 #undef STARTUPINFO
44 #define STARTUPINFO STARTUPINFOA
45 #undef CreateProcess
46 #define CreateProcess CreateProcessA
48 #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*?"
49 #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"
51 /* Returns the length of a quoted argument string. */
52 static size_t
53 quoted_arg_length (const char *string)
55 bool quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
56 size_t length;
57 unsigned int backslashes;
58 const char *s;
60 length = 0;
61 backslashes = 0;
62 if (quote_around)
63 length++;
64 for (s = string; *s != '\0'; s++)
66 char c = *s;
67 if (c == '"')
68 length += backslashes + 1;
69 length++;
70 if (c == '\\')
71 backslashes++;
72 else
73 backslashes = 0;
75 if (quote_around)
76 length += backslashes + 1;
78 return length;
81 /* Produces a quoted argument string.
82 Stores exactly quoted_arg_length (STRING) + 1 bytes, including the final
83 NUL byte, at MEM.
84 Returns a pointer past the stored quoted argument string. */
85 static char *
86 quoted_arg_string (const char *string, char *mem)
88 bool quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
89 char *p;
90 unsigned int backslashes;
91 const char *s;
93 p = mem;
94 backslashes = 0;
95 if (quote_around)
96 *p++ = '"';
97 for (s = string; *s != '\0'; s++)
99 char c = *s;
100 if (c == '"')
102 unsigned int j;
103 for (j = backslashes + 1; j > 0; j--)
104 *p++ = '\\';
106 *p++ = c;
107 if (c == '\\')
108 backslashes++;
109 else
110 backslashes = 0;
112 if (quote_around)
114 unsigned int j;
115 for (j = backslashes; j > 0; j--)
116 *p++ = '\\';
117 *p++ = '"';
119 *p++ = '\0';
121 return p;
124 const char **
125 prepare_spawn (const char * const *argv, char **mem_to_free)
127 size_t argc;
128 const char **new_argv;
129 size_t i;
131 /* Count number of arguments. */
132 for (argc = 0; argv[argc] != NULL; argc++)
135 /* Allocate new argument vector. */
136 new_argv = (const char **) malloc ((1 + argc + 1) * sizeof (const char *));
138 /* Add an element upfront that can be used when argv[0] turns out to be a
139 script, not a program.
140 On Unix, this would be "/bin/sh". On native Windows, "sh" is actually
141 "sh.exe". We have to omit the directory part and rely on the search in
142 PATH, because the mingw "mount points" are not visible inside Windows
143 CreateProcess(). */
144 new_argv[0] = "sh.exe";
146 /* Put quoted arguments into the new argument vector. */
147 size_t needed_size = 0;
148 for (i = 0; i < argc; i++)
150 const char *string = argv[i];
151 size_t length;
153 if (string[0] == '\0')
154 length = strlen ("\"\"");
155 else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
156 length = quoted_arg_length (string);
157 else
158 length = strlen (string);
159 needed_size += length + 1;
162 char *mem;
163 if (needed_size == 0)
164 mem = NULL;
165 else
167 mem = (char *) malloc (needed_size);
168 if (mem == NULL)
170 /* Memory allocation failure. */
171 free (new_argv);
172 errno = ENOMEM;
173 return NULL;
176 *mem_to_free = mem;
178 for (i = 0; i < argc; i++)
180 const char *string = argv[i];
182 new_argv[1 + i] = mem;
183 if (string[0] == '\0')
185 size_t length = strlen ("\"\"");
186 memcpy (mem, "\"\"", length + 1);
187 mem += length + 1;
189 else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
191 mem = quoted_arg_string (string, mem);
193 else
195 size_t length = strlen (string);
196 memcpy (mem, string, length + 1);
197 mem += length + 1;
200 new_argv[1 + argc] = NULL;
202 return new_argv;
205 char *
206 compose_command (const char * const *argv)
208 /* Just concatenate the argv[] strings, separated by spaces. */
209 char *command;
211 /* Determine the size of the needed block of memory. */
212 size_t total_size = 0;
213 const char * const *ap;
214 const char *p;
215 for (ap = argv; (p = *ap) != NULL; ap++)
216 total_size += strlen (p) + 1;
217 size_t command_size = (total_size > 0 ? total_size : 1);
219 /* Allocate the block of memory. */
220 command = (char *) malloc (command_size);
221 if (command == NULL)
223 errno = ENOMEM;
224 return NULL;
227 /* Fill it. */
228 if (total_size > 0)
230 char *cp = command;
231 for (ap = argv; (p = *ap) != NULL; ap++)
233 size_t size = strlen (p) + 1;
234 memcpy (cp, p, size - 1);
235 cp += size;
236 cp[-1] = ' ';
238 cp[-1] = '\0';
240 else
241 *command = '\0';
243 return command;
246 char *
247 compose_envblock (const char * const *envp)
249 /* This is a bit hairy, because we don't have a lock that would prevent other
250 threads from making modifications in ENVP. So, just make sure we don't
251 crash; but if other threads are making modifications, part of the result
252 may be wrong. */
253 retry:
255 /* Guess the size of the needed block of memory.
256 The guess will be exact if other threads don't make modifications. */
257 size_t total_size = 0;
258 const char * const *ep;
259 const char *p;
260 for (ep = envp; (p = *ep) != NULL; ep++)
261 total_size += strlen (p) + 1;
262 size_t envblock_size = total_size;
264 /* Allocate the block of memory. */
265 char *envblock = (char *) malloc (envblock_size + 1);
266 if (envblock == NULL)
268 errno = ENOMEM;
269 return NULL;
271 size_t envblock_used = 0;
272 for (ep = envp; (p = *ep) != NULL; ep++)
274 size_t size = strlen (p) + 1;
275 if (envblock_used + size > envblock_size)
277 /* Other threads did modifications. Need more memory. */
278 envblock_size += envblock_size / 2;
279 if (envblock_used + size > envblock_size)
280 envblock_size = envblock_used + size;
282 char *new_envblock = (char *) realloc (envblock, envblock_size + 1);
283 if (new_envblock == NULL)
285 free (envblock);
286 errno = ENOMEM;
287 return NULL;
289 envblock = new_envblock;
291 memcpy (envblock + envblock_used, p, size);
292 envblock_used += size;
293 if (envblock[envblock_used - 1] != '\0')
295 /* Other threads did modifications. Restart. */
296 free (envblock);
297 goto retry;
300 envblock[envblock_used] = '\0';
301 return envblock;
306 init_inheritable_handles (struct inheritable_handles *inh_handles,
307 bool duplicate)
309 /* Determine the minimal count of handles we need to care about. */
310 size_t handles_count;
312 /* _getmaxstdio
313 <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/getmaxstdio>
314 Default value is 512. */
315 unsigned int fdmax = _getmaxstdio ();
316 if (fdmax < 3)
317 fdmax = 3;
318 for (; fdmax > 3; fdmax--)
320 unsigned int fd = fdmax - 1;
321 /* _get_osfhandle
322 <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle> */
323 HANDLE handle = (HANDLE) _get_osfhandle (fd);
324 if (handle != INVALID_HANDLE_VALUE)
326 if (duplicate)
327 /* We will add fd to the array, regardless of whether it is
328 inheritable or not. */
329 break;
330 else
332 DWORD hflags;
333 /* GetHandleInformation
334 <https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-gethandleinformation> */
335 if (GetHandleInformation (handle, &hflags))
337 if ((hflags & HANDLE_FLAG_INHERIT) != 0)
338 /* fd denotes an inheritable descriptor. */
339 break;
344 handles_count = fdmax;
346 /* Note: handles_count >= 3. */
348 /* Allocate the array. */
349 size_t handles_allocated = handles_count;
350 struct IHANDLE *ih =
351 (struct IHANDLE *) malloc (handles_allocated * sizeof (struct IHANDLE));
352 if (ih == NULL)
354 errno = ENOMEM;
355 return -1;
358 /* Fill in the array. */
360 HANDLE curr_process = (duplicate ? GetCurrentProcess () : INVALID_HANDLE_VALUE);
361 unsigned int fd;
362 for (fd = 0; fd < handles_count; fd++)
364 ih[fd].handle = INVALID_HANDLE_VALUE;
365 /* _get_osfhandle
366 <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle> */
367 HANDLE handle = (HANDLE) _get_osfhandle (fd);
368 if (handle != INVALID_HANDLE_VALUE)
370 DWORD hflags;
371 /* GetHandleInformation
372 <https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-gethandleinformation> */
373 if (GetHandleInformation (handle, &hflags))
375 if (duplicate)
377 /* Add fd to the array, regardless of whether it is
378 inheritable or not. */
379 if ((hflags & HANDLE_FLAG_INHERIT) != 0)
381 /* Instead of duplicating it, just mark it as shared. */
382 ih[fd].handle = handle;
383 ih[fd].flags = KEEP_OPEN_IN_PARENT | KEEP_OPEN_IN_CHILD;
385 else
387 if (!DuplicateHandle (curr_process, handle,
388 curr_process, &ih[fd].handle,
389 0, TRUE, DUPLICATE_SAME_ACCESS))
391 unsigned int i;
392 for (i = 0; i < fd; i++)
393 if (ih[i].handle != INVALID_HANDLE_VALUE
394 && !(ih[i].flags & KEEP_OPEN_IN_PARENT))
395 CloseHandle (ih[i].handle);
396 free (ih);
397 errno = EBADF; /* arbitrary */
398 return -1;
400 ih[fd].flags = 0;
403 else
405 if ((hflags & HANDLE_FLAG_INHERIT) != 0)
407 /* fd denotes an inheritable descriptor. */
408 ih[fd].handle = handle;
409 ih[fd].flags = KEEP_OPEN_IN_CHILD;
417 /* Return the result. */
418 inh_handles->count = handles_count;
419 inh_handles->allocated = handles_allocated;
420 inh_handles->ih = ih;
421 return 0;
425 compose_handles_block (const struct inheritable_handles *inh_handles,
426 STARTUPINFO *sinfo)
428 /* STARTUPINFO
429 <https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa> */
430 sinfo->dwFlags = STARTF_USESTDHANDLES;
431 sinfo->hStdInput = inh_handles->ih[0].handle;
432 sinfo->hStdOutput = inh_handles->ih[1].handle;
433 sinfo->hStdError = inh_handles->ih[2].handle;
435 /* On newer versions of Windows, more file descriptors / handles than the
436 first three can be passed.
437 The format is as follows: Let N be an exclusive upper bound for the file
438 descriptors to be passed. Two arrays are constructed in memory:
439 - flags[0..N-1], of element type 'unsigned char',
440 - handles[0..N-1], of element type 'HANDLE' or 'intptr_t'.
441 For used entries, handles[i] is the handle, and flags[i] is a set of flags,
442 a combination of:
443 1 for open file descriptors,
444 64 for handles of type FILE_TYPE_CHAR,
445 8 for handles of type FILE_TYPE_PIPE,
446 32 for O_APPEND.
447 For unused entries - this may include any of the first three, since they
448 are already passed above -, handles[i] is INVALID_HANDLE_VALUE and flags[i]
449 is zero.
450 lpReserved2 now is a pointer to the concatenation (without padding) of:
451 - an 'unsigned int' whose value is N,
452 - the contents of the flags[0..N-1] array,
453 - the contents of the handles[0..N-1] array.
454 cbReserved2 is the size (in bytes) of the object at lpReserved2. */
456 size_t handles_count = inh_handles->count;
458 sinfo->cbReserved2 =
459 sizeof (unsigned int)
460 + handles_count * sizeof (unsigned char)
461 + handles_count * sizeof (HANDLE);
462 /* Add some padding, so that we can work with a properly aligned HANDLE
463 array. */
464 char *hblock = (char *) malloc (sinfo->cbReserved2 + (sizeof (HANDLE) - 1));
465 if (hblock == NULL)
467 errno = ENOMEM;
468 return -1;
470 unsigned char *flags = (unsigned char *) (hblock + sizeof (unsigned int));
471 char *handles = (char *) (flags + handles_count);
472 HANDLE *handles_aligned =
473 (HANDLE *) (((uintptr_t) handles + (sizeof (HANDLE) - 1))
474 & - (uintptr_t) sizeof (HANDLE));
476 * (unsigned int *) hblock = handles_count;
478 unsigned int fd;
479 for (fd = 0; fd < handles_count; fd++)
481 handles_aligned[fd] = INVALID_HANDLE_VALUE;
482 flags[fd] = 0;
484 HANDLE handle = inh_handles->ih[fd].handle;
485 if (handle != INVALID_HANDLE_VALUE
486 /* The first three are possibly already passed above.
487 But they need to passed here as well, if they have some flags. */
488 && (fd >= 3 || (unsigned char) inh_handles->ih[fd].flags != 0))
490 DWORD hflags;
491 /* GetHandleInformation
492 <https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-gethandleinformation> */
493 if (GetHandleInformation (handle, &hflags))
495 if ((hflags & HANDLE_FLAG_INHERIT) != 0)
497 /* fd denotes an inheritable descriptor. */
498 handles_aligned[fd] = handle;
499 /* On Microsoft Windows, it would be sufficient to set
500 flags[fd] = 1. But on ReactOS or Wine, adding the bit
501 that indicates the handle type may be necessary. So,
502 just do it everywhere. */
503 flags[fd] = 1 | (unsigned char) inh_handles->ih[fd].flags;
504 switch (GetFileType (handle))
506 case FILE_TYPE_CHAR:
507 flags[fd] |= 64;
508 break;
509 case FILE_TYPE_PIPE:
510 flags[fd] |= 8;
511 break;
512 default:
513 break;
516 else
517 /* We shouldn't have any non-inheritable handles in
518 inh_handles->handles. */
519 abort ();
524 if (handles != (char *) handles_aligned)
525 memmove (handles, (char *) handles_aligned, handles_count * sizeof (HANDLE));
527 sinfo->lpReserved2 = (BYTE *) hblock;
529 return 0;
532 void
533 free_inheritable_handles (struct inheritable_handles *inh_handles)
535 free (inh_handles->ih);
539 convert_CreateProcess_error (DWORD error)
541 /* Some of these errors probably cannot happen. But who knows... */
542 switch (error)
544 case ERROR_FILE_NOT_FOUND:
545 case ERROR_PATH_NOT_FOUND:
546 case ERROR_BAD_PATHNAME:
547 case ERROR_BAD_NET_NAME:
548 case ERROR_INVALID_NAME:
549 case ERROR_DIRECTORY:
550 return ENOENT;
551 break;
553 case ERROR_ACCESS_DENIED:
554 case ERROR_SHARING_VIOLATION:
555 return EACCES;
556 break;
558 case ERROR_OUTOFMEMORY:
559 return ENOMEM;
560 break;
562 case ERROR_BUFFER_OVERFLOW:
563 case ERROR_FILENAME_EXCED_RANGE:
564 return ENAMETOOLONG;
565 break;
567 case ERROR_BAD_FORMAT:
568 case ERROR_BAD_EXE_FORMAT:
569 return ENOEXEC;
570 break;
572 default:
573 return EINVAL;
574 break;
578 intptr_t
579 spawnpvech (int mode,
580 const char *progname, const char * const *argv,
581 const char * const *envp,
582 const char *currdir,
583 HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle)
585 /* Validate the arguments. */
586 if (!(mode == P_WAIT
587 || mode == P_NOWAIT
588 || mode == P_DETACH
589 || mode == P_OVERLAY)
590 || progname == NULL || argv == NULL)
592 errno = EINVAL;
593 return -1;
596 /* Implement the 'p' letter: search for PROGNAME in getenv ("PATH"). */
597 const char *resolved_progname =
598 find_in_given_path (progname, getenv ("PATH"), NULL, false);
599 if (resolved_progname == NULL)
600 return -1;
602 /* Compose the command. */
603 char *command = compose_command (argv);
604 if (command == NULL)
605 goto out_of_memory_1;
607 /* Copy *ENVP into a contiguous block of memory. */
608 char *envblock;
609 if (envp == NULL)
610 envblock = NULL;
611 else
613 envblock = compose_envblock (envp);
614 if (envblock == NULL)
615 goto out_of_memory_2;
618 /* Collect the inheritable handles. */
619 struct inheritable_handles inh_handles;
620 if (init_inheritable_handles (&inh_handles, false) < 0)
622 int saved_errno = errno;
623 if (envblock != NULL)
624 free (envblock);
625 free (command);
626 if (resolved_progname != progname)
627 free ((char *) resolved_progname);
628 errno = saved_errno;
629 return -1;
631 inh_handles.ih[0].handle = stdin_handle;
632 inh_handles.ih[0].flags = KEEP_OPEN_IN_CHILD;
633 inh_handles.ih[1].handle = stdout_handle;
634 inh_handles.ih[1].flags = KEEP_OPEN_IN_CHILD;
635 inh_handles.ih[2].handle = stderr_handle;
636 inh_handles.ih[2].flags = KEEP_OPEN_IN_CHILD;
638 /* CreateProcess
639 <https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa> */
640 /* <https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags> */
641 DWORD process_creation_flags = (mode == P_DETACH ? DETACHED_PROCESS : 0);
642 /* STARTUPINFO
643 <https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa> */
644 STARTUPINFO sinfo;
645 sinfo.cb = sizeof (STARTUPINFO);
646 sinfo.lpReserved = NULL;
647 sinfo.lpDesktop = NULL;
648 sinfo.lpTitle = NULL;
649 if (compose_handles_block (&inh_handles, &sinfo) < 0)
651 int saved_errno = errno;
652 free_inheritable_handles (&inh_handles);
653 if (envblock != NULL)
654 free (envblock);
655 free (command);
656 if (resolved_progname != progname)
657 free ((char *) resolved_progname);
658 errno = saved_errno;
659 return -1;
662 PROCESS_INFORMATION pinfo;
663 if (!CreateProcess (resolved_progname, command, NULL, NULL, TRUE,
664 process_creation_flags, envblock, currdir, &sinfo,
665 &pinfo))
667 DWORD error = GetLastError ();
669 free (sinfo.lpReserved2);
670 free_inheritable_handles (&inh_handles);
671 if (envblock != NULL)
672 free (envblock);
673 free (command);
674 if (resolved_progname != progname)
675 free ((char *) resolved_progname);
677 errno = convert_CreateProcess_error (error);
678 return -1;
681 if (pinfo.hThread)
682 CloseHandle (pinfo.hThread);
683 free (sinfo.lpReserved2);
684 free_inheritable_handles (&inh_handles);
685 if (envblock != NULL)
686 free (envblock);
687 free (command);
688 if (resolved_progname != progname)
689 free ((char *) resolved_progname);
691 switch (mode)
693 case P_WAIT:
695 /* Wait until it terminates. Then get its exit status code. */
696 switch (WaitForSingleObject (pinfo.hProcess, INFINITE))
698 case WAIT_OBJECT_0:
699 break;
700 case WAIT_FAILED:
701 errno = ECHILD;
702 return -1;
703 default:
704 abort ();
707 DWORD exit_code;
708 if (!GetExitCodeProcess (pinfo.hProcess, &exit_code))
710 errno = ECHILD;
711 return -1;
713 CloseHandle (pinfo.hProcess);
714 return exit_code;
717 case P_NOWAIT:
718 /* Return pinfo.hProcess, not pinfo.dwProcessId. */
719 return (intptr_t) pinfo.hProcess;
721 case P_DETACH:
722 case P_OVERLAY:
723 CloseHandle (pinfo.hProcess);
724 return 0;
726 default:
727 /* Already checked above. */
728 abort ();
731 /*NOTREACHED*/
732 out_of_memory_2:
733 free (command);
734 out_of_memory_1:
735 if (resolved_progname != progname)
736 free ((char *) resolved_progname);
737 errno = ENOMEM;
738 return -1;