summaryrefslogtreecommitdiff
path: root/lib/windows-spawn.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/windows-spawn.c')
-rw-r--r--lib/windows-spawn.c108
1 files changed, 60 insertions, 48 deletions
diff --git a/lib/windows-spawn.c b/lib/windows-spawn.c
index a9212d485..f864db131 100644
--- a/lib/windows-spawn.c
+++ b/lib/windows-spawn.c
@@ -1,5 +1,5 @@
/* Auxiliary functions for the creation of subprocesses. Native Windows API.
- Copyright (C) 2001, 2003-2022 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2003-2023 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This file is free software: you can redistribute it and/or modify
@@ -24,7 +24,6 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
-#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -324,14 +323,21 @@ init_inheritable_handles (struct inheritable_handles *inh_handles,
HANDLE handle = (HANDLE) _get_osfhandle (fd);
if (handle != INVALID_HANDLE_VALUE)
{
- DWORD hflags;
- /* GetHandleInformation
- <https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-gethandleinformation> */
- if (GetHandleInformation (handle, &hflags))
+ if (duplicate)
+ /* We will add fd to the array, regardless of whether it is
+ inheritable or not. */
+ break;
+ else
{
- if ((hflags & HANDLE_FLAG_INHERIT) != 0)
- /* fd denotes an inheritable descriptor. */
- break;
+ DWORD hflags;
+ /* GetHandleInformation
+ <https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-gethandleinformation> */
+ if (GetHandleInformation (handle, &hflags))
+ {
+ if ((hflags & HANDLE_FLAG_INHERIT) != 0)
+ /* fd denotes an inheritable descriptor. */
+ break;
+ }
}
}
}
@@ -339,31 +345,23 @@ init_inheritable_handles (struct inheritable_handles *inh_handles,
}
/* Note: handles_count >= 3. */
- /* Allocate the arrays. */
+ /* Allocate the array. */
size_t handles_allocated = handles_count;
- HANDLE *handles_array =
- (HANDLE *) malloc (handles_allocated * sizeof (HANDLE));
- if (handles_array == NULL)
- {
- errno = ENOMEM;
- return -1;
- }
- unsigned char *flags_array =
- (unsigned char *) malloc (handles_allocated * sizeof (unsigned char));
- if (flags_array == NULL)
+ struct IHANDLE *ih =
+ (struct IHANDLE *) malloc (handles_allocated * sizeof (struct IHANDLE));
+ if (ih == NULL)
{
- free (handles_array);
errno = ENOMEM;
return -1;
}
- /* Fill in the two arrays. */
+ /* Fill in the array. */
{
HANDLE curr_process = (duplicate ? GetCurrentProcess () : INVALID_HANDLE_VALUE);
unsigned int fd;
for (fd = 0; fd < handles_count; fd++)
{
- handles_array[fd] = INVALID_HANDLE_VALUE;
+ ih[fd].handle = INVALID_HANDLE_VALUE;
/* _get_osfhandle
<https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle> */
HANDLE handle = (HANDLE) _get_osfhandle (fd);
@@ -374,29 +372,42 @@ init_inheritable_handles (struct inheritable_handles *inh_handles,
<https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-gethandleinformation> */
if (GetHandleInformation (handle, &hflags))
{
- if ((hflags & HANDLE_FLAG_INHERIT) != 0)
+ if (duplicate)
{
- /* fd denotes an inheritable descriptor. */
- if (duplicate)
+ /* Add fd to the array, regardless of whether it is
+ inheritable or not. */
+ if ((hflags & HANDLE_FLAG_INHERIT) != 0)
+ {
+ /* Instead of duplicating it, just mark it as shared. */
+ ih[fd].handle = handle;
+ ih[fd].flags = KEEP_OPEN_IN_PARENT | KEEP_OPEN_IN_CHILD;
+ }
+ else
{
if (!DuplicateHandle (curr_process, handle,
- curr_process, &handles_array[fd],
+ curr_process, &ih[fd].handle,
0, TRUE, DUPLICATE_SAME_ACCESS))
{
unsigned int i;
for (i = 0; i < fd; i++)
- if (handles_array[i] != INVALID_HANDLE_VALUE)
- CloseHandle (handles_array[i]);
- free (flags_array);
- free (handles_array);
+ if (ih[i].handle != INVALID_HANDLE_VALUE
+ && !(ih[i].flags & KEEP_OPEN_IN_PARENT))
+ CloseHandle (ih[i].handle);
+ free (ih);
errno = EBADF; /* arbitrary */
return -1;
}
+ ih[fd].flags = 0;
+ }
+ }
+ else
+ {
+ if ((hflags & HANDLE_FLAG_INHERIT) != 0)
+ {
+ /* fd denotes an inheritable descriptor. */
+ ih[fd].handle = handle;
+ ih[fd].flags = KEEP_OPEN_IN_CHILD;
}
- else
- handles_array[fd] = handle;
-
- flags_array[fd] = 0;
}
}
}
@@ -406,8 +417,7 @@ init_inheritable_handles (struct inheritable_handles *inh_handles,
/* Return the result. */
inh_handles->count = handles_count;
inh_handles->allocated = handles_allocated;
- inh_handles->handles = handles_array;
- inh_handles->flags = flags_array;
+ inh_handles->ih = ih;
return 0;
}
@@ -418,9 +428,9 @@ compose_handles_block (const struct inheritable_handles *inh_handles,
/* STARTUPINFO
<https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa> */
sinfo->dwFlags = STARTF_USESTDHANDLES;
- sinfo->hStdInput = inh_handles->handles[0];
- sinfo->hStdOutput = inh_handles->handles[1];
- sinfo->hStdError = inh_handles->handles[2];
+ sinfo->hStdInput = inh_handles->ih[0].handle;
+ sinfo->hStdOutput = inh_handles->ih[1].handle;
+ sinfo->hStdError = inh_handles->ih[2].handle;
/* On newer versions of Windows, more file descriptors / handles than the
first three can be passed.
@@ -471,11 +481,11 @@ compose_handles_block (const struct inheritable_handles *inh_handles,
handles_aligned[fd] = INVALID_HANDLE_VALUE;
flags[fd] = 0;
- HANDLE handle = inh_handles->handles[fd];
+ HANDLE handle = inh_handles->ih[fd].handle;
if (handle != INVALID_HANDLE_VALUE
/* The first three are possibly already passed above.
But they need to passed here as well, if they have some flags. */
- && (fd >= 3 || inh_handles->flags[fd] != 0))
+ && (fd >= 3 || (unsigned char) inh_handles->ih[fd].flags != 0))
{
DWORD hflags;
/* GetHandleInformation
@@ -490,7 +500,7 @@ compose_handles_block (const struct inheritable_handles *inh_handles,
flags[fd] = 1. But on ReactOS or Wine, adding the bit
that indicates the handle type may be necessary. So,
just do it everywhere. */
- flags[fd] = 1 | inh_handles->flags[fd];
+ flags[fd] = 1 | (unsigned char) inh_handles->ih[fd].flags;
switch (GetFileType (handle))
{
case FILE_TYPE_CHAR:
@@ -522,8 +532,7 @@ compose_handles_block (const struct inheritable_handles *inh_handles,
void
free_inheritable_handles (struct inheritable_handles *inh_handles)
{
- free (inh_handles->flags);
- free (inh_handles->handles);
+ free (inh_handles->ih);
}
int
@@ -619,9 +628,12 @@ spawnpvech (int mode,
errno = saved_errno;
return -1;
}
- inh_handles.handles[0] = stdin_handle; inh_handles.flags[0] = 0;
- inh_handles.handles[1] = stdout_handle; inh_handles.flags[1] = 0;
- inh_handles.handles[2] = stderr_handle; inh_handles.flags[2] = 0;
+ inh_handles.ih[0].handle = stdin_handle;
+ inh_handles.ih[0].flags = KEEP_OPEN_IN_CHILD;
+ inh_handles.ih[1].handle = stdout_handle;
+ inh_handles.ih[1].flags = KEEP_OPEN_IN_CHILD;
+ inh_handles.ih[2].handle = stderr_handle;
+ inh_handles.ih[2].flags = KEEP_OPEN_IN_CHILD;
/* CreateProcess
<https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa> */