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 spawnpvech (int mode
,
308 const char *progname
, const char * const *argv
,
309 const char * const *envp
,
311 HANDLE stdin_handle
, HANDLE stdout_handle
, HANDLE stderr_handle
)
313 /* Validate the arguments. */
317 || mode
== P_OVERLAY
)
318 || progname
== NULL
|| argv
== NULL
)
324 /* Implement the 'p' letter: search for PROGNAME in getenv ("PATH"). */
325 const char *resolved_progname
=
326 find_in_given_path (progname
, getenv ("PATH"), NULL
, false);
327 if (resolved_progname
== NULL
)
330 /* Compose the command. */
331 char *command
= compose_command (argv
);
333 goto out_of_memory_1
;
335 /* Copy *ENVP into a contiguous block of memory. */
341 envblock
= compose_envblock (envp
);
342 if (envblock
== NULL
)
343 goto out_of_memory_2
;
347 <https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa> */
348 /* Regarding handle inheritance, see
349 <https://docs.microsoft.com/en-us/windows/win32/sysinfo/handle-inheritance> */
350 /* <https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags> */
351 DWORD process_creation_flags
= (mode
== P_DETACH
? DETACHED_PROCESS
: 0);
353 <https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa> */
355 sinfo
.cb
= sizeof (STARTUPINFO
);
356 sinfo
.lpReserved
= NULL
;
357 sinfo
.lpDesktop
= NULL
;
358 sinfo
.lpTitle
= NULL
;
359 sinfo
.dwFlags
= STARTF_USESTDHANDLES
;
360 sinfo
.hStdInput
= stdin_handle
;
361 sinfo
.hStdOutput
= stdout_handle
;
362 sinfo
.hStdError
= stderr_handle
;
366 sinfo
.cbReserved2
= 0;
367 sinfo
.lpReserved2
= NULL
;
369 /* On newer versions of Windows, more file descriptors / handles than the
370 first three can be passed.
371 The format is as follows: Let N be an exclusive upper bound for the file
372 descriptors to be passed. Two arrays are constructed in memory:
373 - flags[0..N-1], of element type 'unsigned char',
374 - handles[0..N-1], of element type 'HANDLE' or 'intptr_t'.
375 For used entries, handles[i] is the handle, and flags[i] is a set of flags,
377 1 for open file descriptors,
378 64 for handles of type FILE_TYPE_CHAR,
379 8 for handles of type FILE_TYPE_PIPE.
380 For unused entries - this includes the first three, since they are already
381 passed above -, handles[i] is INVALID_HANDLE_VALUE and flags[i] is zero.
382 lpReserved2 now is a pointer to the concatenation (without padding) of:
383 - an 'unsigned int' whose value is N,
384 - the contents of the flags[0..N-1] array,
385 - the contents of the handles[0..N-1] array.
386 cbReserved2 is the size (in bytes) of the object at lpReserved2. */
389 <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/getmaxstdio>
390 Default value is 512. */
392 for (fdmax
= _getmaxstdio (); fdmax
> 0; fdmax
--)
394 unsigned int fd
= fdmax
- 1;
396 <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle> */
397 HANDLE handle
= (HANDLE
) _get_osfhandle (fd
);
398 if (handle
!= INVALID_HANDLE_VALUE
)
401 /* GetHandleInformation
402 <https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-gethandleinformation> */
403 if (GetHandleInformation (handle
, &hflags
))
405 if ((hflags
& HANDLE_FLAG_INHERIT
) != 0)
406 /* fd denotes an inheritable descriptor. */
414 sizeof (unsigned int)
415 + fdmax
* sizeof (unsigned char)
416 + fdmax
* sizeof (HANDLE
);
417 /* Add some padding, so that we can work with a properly HANDLE array. */
418 hblock
= (char *) malloc (sinfo
.cbReserved2
+ (sizeof (HANDLE
) - 1));
420 goto out_of_memory_3
;
421 * (unsigned int *) hblock
= fdmax
;
422 unsigned char *flags
= (unsigned char *) (hblock
+ sizeof (unsigned int));
423 char *handles
= (char *) (flags
+ fdmax
);
424 HANDLE
*handles_aligned
=
425 (HANDLE
*) (((uintptr_t) handles
+ (sizeof (HANDLE
) - 1))
426 & - (uintptr_t) sizeof (HANDLE
));
429 for (fd
= 0; fd
< fdmax
; fd
++)
432 handles_aligned
[fd
] = INVALID_HANDLE_VALUE
;
433 /* The first three are already passed above. */
437 <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle> */
438 HANDLE handle
= (HANDLE
) _get_osfhandle (fd
);
439 if (handle
!= INVALID_HANDLE_VALUE
)
442 /* GetHandleInformation
443 <https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-gethandleinformation> */
444 if (GetHandleInformation (handle
, &hflags
))
446 if ((hflags
& HANDLE_FLAG_INHERIT
) != 0)
448 /* fd denotes an inheritable descriptor. */
449 /* On Microsoft Windows, it would be sufficient to
450 set flags[fd] = 1. But on ReactOS or Wine,
451 adding the bit that indicates the handle type
452 may be necessary. So, just do it everywhere. */
453 switch (GetFileType (handle
))
465 handles_aligned
[fd
] = handle
;
472 if (handles
!= (char *) handles_aligned
)
473 memmove (handles
, (char *) handles_aligned
, fdmax
* sizeof (HANDLE
));
474 sinfo
.lpReserved2
= (BYTE
*) hblock
;
478 sinfo
.cbReserved2
= 0;
479 sinfo
.lpReserved2
= NULL
;
484 PROCESS_INFORMATION pinfo
;
485 if (!CreateProcess (resolved_progname
, command
, NULL
, NULL
, TRUE
,
486 process_creation_flags
, envblock
, currdir
, &sinfo
,
489 DWORD error
= GetLastError ();
493 if (envblock
!= NULL
)
496 if (resolved_progname
!= progname
)
497 free ((char *) resolved_progname
);
499 /* Some of these errors probably cannot happen. But who knows... */
502 case ERROR_FILE_NOT_FOUND
:
503 case ERROR_PATH_NOT_FOUND
:
504 case ERROR_BAD_PATHNAME
:
505 case ERROR_BAD_NET_NAME
:
506 case ERROR_INVALID_NAME
:
507 case ERROR_DIRECTORY
:
511 case ERROR_ACCESS_DENIED
:
512 case ERROR_SHARING_VIOLATION
:
516 case ERROR_OUTOFMEMORY
:
520 case ERROR_BUFFER_OVERFLOW
:
521 case ERROR_FILENAME_EXCED_RANGE
:
522 errno
= ENAMETOOLONG
;
525 case ERROR_BAD_FORMAT
:
526 case ERROR_BAD_EXE_FORMAT
:
539 CloseHandle (pinfo
.hThread
);
542 if (envblock
!= NULL
)
545 if (resolved_progname
!= progname
)
546 free ((char *) resolved_progname
);
552 /* Wait until it terminates. Then get its exit status code. */
553 switch (WaitForSingleObject (pinfo
.hProcess
, INFINITE
))
565 if (!GetExitCodeProcess (pinfo
.hProcess
, &exit_code
))
570 CloseHandle (pinfo
.hProcess
);
575 /* Return pinfo.hProcess, not pinfo.dwProcessId. */
576 return (intptr_t) pinfo
.hProcess
;
580 CloseHandle (pinfo
.hProcess
);
584 /* Already checked above. */
595 if (envblock
!= NULL
)
600 if (resolved_progname
!= progname
)
601 free ((char *) resolved_progname
);