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/>. */
21 #include "windows-spawn.h"
23 /* Get declarations of the native Windows API functions. */
24 #define WIN32_LEAN_AND_MEAN
33 /* Get _get_osfhandle(). */
34 #if GNULIB_MSVC_NOTHROW
35 # include "msvc-nothrow.h"
43 /* Don't assume that UNICODE is not defined. */
45 #define STARTUPINFO STARTUPINFOA
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. */
54 quoted_arg_length (const char *string
)
56 bool quote_around
= (strpbrk (string
, SHELL_SPACE_CHARS
) != NULL
);
58 unsigned int backslashes
;
65 for (s
= string
; *s
!= '\0'; s
++)
69 length
+= backslashes
+ 1;
77 length
+= backslashes
+ 1;
82 /* Produces a quoted argument string.
83 Stores exactly quoted_arg_length (STRING) + 1 bytes, including the final
85 Returns a pointer past the stored quoted argument string. */
87 quoted_arg_string (const char *string
, char *mem
)
89 bool quote_around
= (strpbrk (string
, SHELL_SPACE_CHARS
) != NULL
);
91 unsigned int backslashes
;
98 for (s
= string
; *s
!= '\0'; s
++)
104 for (j
= backslashes
+ 1; j
> 0; j
--)
116 for (j
= backslashes
; j
> 0; j
--)
126 prepare_spawn (const char * const *argv
, char **mem_to_free
)
129 const char **new_argv
;
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
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
];
154 if (string
[0] == '\0')
155 length
= strlen ("\"\"");
156 else if (strpbrk (string
, SHELL_SPECIAL_CHARS
) != NULL
)
157 length
= quoted_arg_length (string
);
159 length
= strlen (string
);
160 needed_size
+= length
+ 1;
164 if (needed_size
== 0)
168 mem
= (char *) malloc (needed_size
);
171 /* Memory allocation failure. */
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);
190 else if (strpbrk (string
, SHELL_SPECIAL_CHARS
) != NULL
)
192 mem
= quoted_arg_string (string
, mem
);
196 size_t length
= strlen (string
);
197 memcpy (mem
, string
, length
+ 1);
201 new_argv
[1 + argc
] = NULL
;
207 compose_command (const char * const *argv
)
209 /* Just concatenate the argv[] strings, separated by spaces. */
212 /* Determine the size of the needed block of memory. */
213 size_t total_size
= 0;
214 const char * const *ap
;
216 for (ap
= argv
; (p
= *ap
) != NULL
; ap
++)
217 total_size
+= strlen (p
) + 1;
218 size_t command_size
= (total_size
> 0 ? total_size
: 1);
220 /* Allocate the block of memory. */
221 command
= (char *) malloc (command_size
);
232 for (ap
= argv
; (p
= *ap
) != NULL
; ap
++)
234 size_t size
= strlen (p
) + 1;
235 memcpy (cp
, p
, size
- 1);
248 compose_envblock (const char * const *envp
)
250 /* This is a bit hairy, because we don't have a lock that would prevent other
251 threads from making modifications in ENVP. So, just make sure we don't
252 crash; but if other threads are making modifications, part of the result
256 /* Guess the size of the needed block of memory.
257 The guess will be exact if other threads don't make modifications. */
258 size_t total_size
= 0;
259 const char * const *ep
;
261 for (ep
= envp
; (p
= *ep
) != NULL
; ep
++)
262 total_size
+= strlen (p
) + 1;
263 size_t envblock_size
= total_size
;
265 /* Allocate the block of memory. */
266 char *envblock
= (char *) malloc (envblock_size
+ 1);
267 if (envblock
== NULL
)
272 size_t envblock_used
= 0;
273 for (ep
= envp
; (p
= *ep
) != NULL
; ep
++)
275 size_t size
= strlen (p
) + 1;
276 if (envblock_used
+ size
> envblock_size
)
278 /* Other threads did modifications. Need more memory. */
279 envblock_size
+= envblock_size
/ 2;
280 if (envblock_used
+ size
> envblock_size
)
281 envblock_size
= envblock_used
+ size
;
283 char *new_envblock
= (char *) realloc (envblock
, envblock_size
+ 1);
284 if (new_envblock
== NULL
)
290 envblock
= new_envblock
;
292 memcpy (envblock
+ envblock_used
, p
, size
);
293 envblock_used
+= size
;
294 if (envblock
[envblock_used
- 1] != '\0')
296 /* Other threads did modifications. Restart. */
301 envblock
[envblock_used
] = '\0';
307 init_inheritable_handles (struct inheritable_handles
*inh_handles
,
310 /* Determine the minimal count of handles we need to care about. */
311 size_t handles_count
;
314 <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/getmaxstdio>
315 Default value is 512. */
316 unsigned int fdmax
= _getmaxstdio ();
319 for (; fdmax
> 3; fdmax
--)
321 unsigned int fd
= fdmax
- 1;
323 <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle> */
324 HANDLE handle
= (HANDLE
) _get_osfhandle (fd
);
325 if (handle
!= INVALID_HANDLE_VALUE
)
328 /* GetHandleInformation
329 <https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-gethandleinformation> */
330 if (GetHandleInformation (handle
, &hflags
))
332 if ((hflags
& HANDLE_FLAG_INHERIT
) != 0)
333 /* fd denotes an inheritable descriptor. */
338 handles_count
= fdmax
;
340 /* Note: handles_count >= 3. */
342 /* Allocate the arrays. */
343 size_t handles_allocated
= handles_count
;
344 HANDLE
*handles_array
=
345 (HANDLE
*) malloc (handles_allocated
* sizeof (HANDLE
));
346 if (handles_array
== NULL
)
351 unsigned char *flags_array
=
352 (unsigned char *) malloc (handles_allocated
* sizeof (unsigned char));
353 if (flags_array
== NULL
)
355 free (handles_array
);
360 /* Fill in the two arrays. */
362 HANDLE curr_process
= (duplicate
? GetCurrentProcess () : INVALID_HANDLE_VALUE
);
364 for (fd
= 0; fd
< handles_count
; fd
++)
366 handles_array
[fd
] = INVALID_HANDLE_VALUE
;
368 <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle> */
369 HANDLE handle
= (HANDLE
) _get_osfhandle (fd
);
370 if (handle
!= INVALID_HANDLE_VALUE
)
373 /* GetHandleInformation
374 <https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-gethandleinformation> */
375 if (GetHandleInformation (handle
, &hflags
))
377 if ((hflags
& HANDLE_FLAG_INHERIT
) != 0)
379 /* fd denotes an inheritable descriptor. */
382 if (!DuplicateHandle (curr_process
, handle
,
383 curr_process
, &handles_array
[fd
],
384 0, TRUE
, DUPLICATE_SAME_ACCESS
))
387 for (i
= 0; i
< fd
; i
++)
388 if (handles_array
[i
] != INVALID_HANDLE_VALUE
)
389 CloseHandle (handles_array
[i
]);
391 free (handles_array
);
392 errno
= EBADF
; /* arbitrary */
397 handles_array
[fd
] = handle
;
406 /* Return the result. */
407 inh_handles
->count
= handles_count
;
408 inh_handles
->allocated
= handles_allocated
;
409 inh_handles
->handles
= handles_array
;
410 inh_handles
->flags
= flags_array
;
415 compose_handles_block (const struct inheritable_handles
*inh_handles
,
419 <https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa> */
420 sinfo
->dwFlags
= STARTF_USESTDHANDLES
;
421 sinfo
->hStdInput
= inh_handles
->handles
[0];
422 sinfo
->hStdOutput
= inh_handles
->handles
[1];
423 sinfo
->hStdError
= inh_handles
->handles
[2];
425 /* On newer versions of Windows, more file descriptors / handles than the
426 first three can be passed.
427 The format is as follows: Let N be an exclusive upper bound for the file
428 descriptors to be passed. Two arrays are constructed in memory:
429 - flags[0..N-1], of element type 'unsigned char',
430 - handles[0..N-1], of element type 'HANDLE' or 'intptr_t'.
431 For used entries, handles[i] is the handle, and flags[i] is a set of flags,
433 1 for open file descriptors,
434 64 for handles of type FILE_TYPE_CHAR,
435 8 for handles of type FILE_TYPE_PIPE,
437 For unused entries - this may include any of the first three, since they
438 are already passed above -, handles[i] is INVALID_HANDLE_VALUE and flags[i]
440 lpReserved2 now is a pointer to the concatenation (without padding) of:
441 - an 'unsigned int' whose value is N,
442 - the contents of the flags[0..N-1] array,
443 - the contents of the handles[0..N-1] array.
444 cbReserved2 is the size (in bytes) of the object at lpReserved2. */
446 size_t handles_count
= inh_handles
->count
;
449 sizeof (unsigned int)
450 + handles_count
* sizeof (unsigned char)
451 + handles_count
* sizeof (HANDLE
);
452 /* Add some padding, so that we can work with a properly aligned HANDLE
454 char *hblock
= (char *) malloc (sinfo
->cbReserved2
+ (sizeof (HANDLE
) - 1));
460 unsigned char *flags
= (unsigned char *) (hblock
+ sizeof (unsigned int));
461 char *handles
= (char *) (flags
+ handles_count
);
462 HANDLE
*handles_aligned
=
463 (HANDLE
*) (((uintptr_t) handles
+ (sizeof (HANDLE
) - 1))
464 & - (uintptr_t) sizeof (HANDLE
));
466 * (unsigned int *) hblock
= handles_count
;
469 for (fd
= 0; fd
< handles_count
; fd
++)
471 handles_aligned
[fd
] = INVALID_HANDLE_VALUE
;
474 HANDLE handle
= inh_handles
->handles
[fd
];
475 if (handle
!= INVALID_HANDLE_VALUE
476 /* The first three are possibly already passed above.
477 But they need to passed here as well, if they have some flags. */
478 && (fd
>= 3 || inh_handles
->flags
[fd
] != 0))
481 /* GetHandleInformation
482 <https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-gethandleinformation> */
483 if (GetHandleInformation (handle
, &hflags
))
485 if ((hflags
& HANDLE_FLAG_INHERIT
) != 0)
487 /* fd denotes an inheritable descriptor. */
488 handles_aligned
[fd
] = handle
;
489 /* On Microsoft Windows, it would be sufficient to set
490 flags[fd] = 1. But on ReactOS or Wine, adding the bit
491 that indicates the handle type may be necessary. So,
492 just do it everywhere. */
493 flags
[fd
] = 1 | inh_handles
->flags
[fd
];
494 switch (GetFileType (handle
))
507 /* We shouldn't have any non-inheritable handles in
508 inh_handles->handles. */
514 if (handles
!= (char *) handles_aligned
)
515 memmove (handles
, (char *) handles_aligned
, handles_count
* sizeof (HANDLE
));
517 sinfo
->lpReserved2
= (BYTE
*) hblock
;
523 free_inheritable_handles (struct inheritable_handles
*inh_handles
)
525 free (inh_handles
->flags
);
526 free (inh_handles
->handles
);
530 convert_CreateProcess_error (DWORD error
)
532 /* Some of these errors probably cannot happen. But who knows... */
535 case ERROR_FILE_NOT_FOUND
:
536 case ERROR_PATH_NOT_FOUND
:
537 case ERROR_BAD_PATHNAME
:
538 case ERROR_BAD_NET_NAME
:
539 case ERROR_INVALID_NAME
:
540 case ERROR_DIRECTORY
:
544 case ERROR_ACCESS_DENIED
:
545 case ERROR_SHARING_VIOLATION
:
549 case ERROR_OUTOFMEMORY
:
553 case ERROR_BUFFER_OVERFLOW
:
554 case ERROR_FILENAME_EXCED_RANGE
:
558 case ERROR_BAD_FORMAT
:
559 case ERROR_BAD_EXE_FORMAT
:
570 spawnpvech (int mode
,
571 const char *progname
, const char * const *argv
,
572 const char * const *envp
,
574 HANDLE stdin_handle
, HANDLE stdout_handle
, HANDLE stderr_handle
)
576 /* Validate the arguments. */
580 || mode
== P_OVERLAY
)
581 || progname
== NULL
|| argv
== NULL
)
587 /* Implement the 'p' letter: search for PROGNAME in getenv ("PATH"). */
588 const char *resolved_progname
=
589 find_in_given_path (progname
, getenv ("PATH"), NULL
, false);
590 if (resolved_progname
== NULL
)
593 /* Compose the command. */
594 char *command
= compose_command (argv
);
596 goto out_of_memory_1
;
598 /* Copy *ENVP into a contiguous block of memory. */
604 envblock
= compose_envblock (envp
);
605 if (envblock
== NULL
)
606 goto out_of_memory_2
;
609 /* Collect the inheritable handles. */
610 struct inheritable_handles inh_handles
;
611 if (init_inheritable_handles (&inh_handles
, false) < 0)
613 int saved_errno
= errno
;
614 if (envblock
!= NULL
)
617 if (resolved_progname
!= progname
)
618 free ((char *) resolved_progname
);
622 inh_handles
.handles
[0] = stdin_handle
; inh_handles
.flags
[0] = 0;
623 inh_handles
.handles
[1] = stdout_handle
; inh_handles
.flags
[1] = 0;
624 inh_handles
.handles
[2] = stderr_handle
; inh_handles
.flags
[2] = 0;
627 <https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa> */
628 /* <https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags> */
629 DWORD process_creation_flags
= (mode
== P_DETACH
? DETACHED_PROCESS
: 0);
631 <https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa> */
633 sinfo
.cb
= sizeof (STARTUPINFO
);
634 sinfo
.lpReserved
= NULL
;
635 sinfo
.lpDesktop
= NULL
;
636 sinfo
.lpTitle
= NULL
;
637 if (compose_handles_block (&inh_handles
, &sinfo
) < 0)
639 int saved_errno
= errno
;
640 free_inheritable_handles (&inh_handles
);
641 if (envblock
!= NULL
)
644 if (resolved_progname
!= progname
)
645 free ((char *) resolved_progname
);
650 PROCESS_INFORMATION pinfo
;
651 if (!CreateProcess (resolved_progname
, command
, NULL
, NULL
, TRUE
,
652 process_creation_flags
, envblock
, currdir
, &sinfo
,
655 DWORD error
= GetLastError ();
657 free (sinfo
.lpReserved2
);
658 free_inheritable_handles (&inh_handles
);
659 if (envblock
!= NULL
)
662 if (resolved_progname
!= progname
)
663 free ((char *) resolved_progname
);
665 errno
= convert_CreateProcess_error (error
);
670 CloseHandle (pinfo
.hThread
);
671 free (sinfo
.lpReserved2
);
672 free_inheritable_handles (&inh_handles
);
673 if (envblock
!= NULL
)
676 if (resolved_progname
!= progname
)
677 free ((char *) resolved_progname
);
683 /* Wait until it terminates. Then get its exit status code. */
684 switch (WaitForSingleObject (pinfo
.hProcess
, INFINITE
))
696 if (!GetExitCodeProcess (pinfo
.hProcess
, &exit_code
))
701 CloseHandle (pinfo
.hProcess
);
706 /* Return pinfo.hProcess, not pinfo.dwProcessId. */
707 return (intptr_t) pinfo
.hProcess
;
711 CloseHandle (pinfo
.hProcess
);
715 /* Already checked above. */
723 if (resolved_progname
!= progname
)
724 free ((char *) resolved_progname
);