1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-01-03 12:11:33 +01:00

spawn: Remove spawn callback, introduce gnupg_spawn_actions.

* common/exechelp-posix.c (call_spawn_cb): Remove.
(gnupg_spawn_actions_new, gnupg_spawn_actions_release)
(gnupg_spawn_actions_set_environ, gnupg_spawn_actions_set_atfork)
(gnupg_spawn_actions_set_redirect)
(gnupg_spawn_actions_set_inherit_fds): New.
(my_exec, spawn_detached): Use spawn actions.
(gnupg_spawn_helper): Remove.
(gnupg_process_spawn): Remove callback, introduce gnupg_spawn_actions.
* common/exechelp-w32.c: Ditto.
* common/exechelp.h: Ditto.
* agent/genkey.c (do_check_passphrase_pattern): Follow the change of
gnupg_process_spawn API.
* common/asshelp.c (start_new_service): Likewise.
* common/exectool.c (gnupg_exec_tool_stream): Likewise.
* common/t-exechelp.c (test_pipe_stream): Likewise.
* dirmngr/ldap-wrapper.c (ldap_wrapper): Likewise.
* g10/photoid.c (run_with_pipe): Likewise.
* scd/app.c (report_change): Likewise.
* tests/gpgscm/ffi.c (do_process_spawn_io, do_process_spawn_fd):
Likewise.
* tools/gpg-card.c (cmd_gpg): Likewise.
* tools/gpgconf-comp.c (gpg_agent_runtime_change): Likewise.
(scdaemon_runtime_change, tpm2daemon_runtime_change)
(dirmngr_runtime_change, keyboxd_runtime_change)
(gc_component_launch, gc_component_check_options)
(retrieve_options_from_program): Likewise.
* tools/gpgconf.c (show_versions_via_dirmngr): Likewise.
* tools/gpgtar-create.c (gpgtar_create): Likewise.
* tools/gpgtar-extract.c (gpgtar_extract): Likewise.
* tools/gpgtar-list.c (gpgtar_list): Likewise.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2024-05-31 15:36:39 +09:00
parent 34045ed9e1
commit fc3fde1bde
No known key found for this signature in database
GPG Key ID: 640114AF89DE6054
17 changed files with 351 additions and 181 deletions

View File

@ -207,7 +207,7 @@ do_check_passphrase_pattern (ctrl_t ctrl, const char *pw, unsigned int flags)
if (gnupg_process_spawn (pgmname, argv, if (gnupg_process_spawn (pgmname, argv,
GNUPG_PROCESS_STDIN_PIPE, GNUPG_PROCESS_STDIN_PIPE,
NULL, NULL, &proc)) NULL, &proc))
result = 1; /* Execute error - assume password should no be used. */ result = 1; /* Execute error - assume password should no be used. */
else else
{ {

View File

@ -525,11 +525,10 @@ start_new_service (assuan_context_t *r_ctx,
{ {
#ifdef HAVE_W32_SYSTEM #ifdef HAVE_W32_SYSTEM
err = gnupg_process_spawn (program? program : program_name, argv, err = gnupg_process_spawn (program? program : program_name, argv,
GNUPG_PROCESS_DETACHED, GNUPG_PROCESS_DETACHED, NULL, NULL);
NULL, NULL, NULL);
#else /*!W32*/ #else /*!W32*/
err = gnupg_process_spawn (program? program : program_name, argv, err = gnupg_process_spawn (program? program : program_name, argv,
0, NULL, NULL, NULL); 0, NULL, NULL);
#endif /*!W32*/ #endif /*!W32*/
if (err) if (err)
log_error ("failed to start %s '%s': %s\n", log_error ("failed to start %s '%s': %s\n",

View File

@ -182,7 +182,7 @@ get_max_fds (void)
which shall not be closed. This list shall be sorted in ascending which shall not be closed. This list shall be sorted in ascending
order with the end marked by -1. */ order with the end marked by -1. */
void void
close_all_fds (int first, int *except) close_all_fds (int first, const int *except)
{ {
int max_fd = get_max_fds (); int max_fd = get_max_fds ();
int fd, i, except_start; int fd, i, except_start;
@ -429,46 +429,105 @@ posix_open_null (int for_write)
return fd; return fd;
} }
static void struct gnupg_spawn_actions {
call_spawn_cb (struct spawn_cb_arg *sca, int fd[3];
int fd_in, int fd_out, int fd_err, const int *except_fds;
void (*spawn_cb) (struct spawn_cb_arg *), void *spawn_cb_arg) char **environ;
void (*atfork) (void *);
void *atfork_arg;
};
gpg_err_code_t
gnupg_spawn_actions_new (gnupg_spawn_actions_t *r_act)
{ {
sca->fds[0] = fd_in; gnupg_spawn_actions_t act;
sca->fds[1] = fd_out; int i;
sca->fds[2] = fd_err;
sca->except_fds = NULL; *r_act = NULL;
sca->arg = spawn_cb_arg;
if (spawn_cb) act = xtrycalloc (1, sizeof (struct gnupg_spawn_actions));
(*spawn_cb) (sca); if (act == NULL)
return gpg_err_code_from_syserror ();
for (i = 0; i <= 2; i++)
act->fd[i] = -1;
*r_act = act;
return 0;
}
void
gnupg_spawn_actions_release (gnupg_spawn_actions_t act)
{
if (!act)
return;
xfree (act);
}
void
gnupg_spawn_actions_set_environ (gnupg_spawn_actions_t act,
char **environ_for_child)
{
act->environ = environ_for_child;
}
void
gnupg_spawn_actions_set_atfork (gnupg_spawn_actions_t act,
void (*atfork)(void *), void *arg)
{
act->atfork = atfork;
act->atfork_arg = arg;
}
void
gnupg_spawn_actions_set_redirect (gnupg_spawn_actions_t act,
int in, int out, int err)
{
act->fd[0] = in;
act->fd[1] = out;
act->fd[2] = err;
}
void
gnupg_spawn_actions_set_inherit_fds (gnupg_spawn_actions_t act,
const int *fds)
{
act->except_fds = fds;
} }
static void static void
my_exec (const char *pgmname, const char *argv[], struct spawn_cb_arg *sca) my_exec (const char *pgmname, const char *argv[], gnupg_spawn_actions_t act)
{ {
int i; int i;
/* Assign /dev/null to unused FDs. */ /* Assign /dev/null to unused FDs. */
for (i = 0; i <= 2; i++) for (i = 0; i <= 2; i++)
if (sca->fds[i] == -1) if (act->fd[i] == -1)
sca->fds[i] = posix_open_null (i); act->fd[i] = posix_open_null (i);
/* Connect the standard files. */ /* Connect the standard files. */
for (i = 0; i <= 2; i++) for (i = 0; i <= 2; i++)
if (sca->fds[i] != i) if (act->fd[i] != i)
{ {
if (dup2 (sca->fds[i], i) == -1) if (dup2 (act->fd[i], i) == -1)
log_fatal ("dup2 std%s failed: %s\n", log_fatal ("dup2 std%s failed: %s\n",
i==0?"in":i==1?"out":"err", strerror (errno)); i==0?"in":i==1?"out":"err", strerror (errno));
/* /*
* We don't close sca.fds[i] here, but close them by * We don't close act->fd[i] here, but close them by
* close_all_fds. Note that there may be same one in three of * close_all_fds. Note that there may be same one in three of
* sca->fds[i]. * act->fd[i].
*/ */
} }
/* Close all other files. */ /* Close all other files. */
close_all_fds (3, sca->except_fds); close_all_fds (3, act->except_fds);
if (act->environ)
environ = act->environ;
if (act->atfork)
act->atfork (act->atfork_arg);
execv (pgmname, (char *const *)argv); execv (pgmname, (char *const *)argv);
/* No way to print anything, as we have may have closed all streams. */ /* No way to print anything, as we have may have closed all streams. */
@ -477,7 +536,7 @@ my_exec (const char *pgmname, const char *argv[], struct spawn_cb_arg *sca)
static gpg_err_code_t static gpg_err_code_t
spawn_detached (const char *pgmname, const char *argv[], spawn_detached (const char *pgmname, const char *argv[],
void (*spawn_cb) (struct spawn_cb_arg *), void *spawn_cb_arg) gnupg_spawn_actions_t act)
{ {
gpg_err_code_t ec; gpg_err_code_t ec;
pid_t pid; pid_t pid;
@ -510,7 +569,6 @@ spawn_detached (const char *pgmname, const char *argv[],
if (!pid) if (!pid)
{ {
pid_t pid2; pid_t pid2;
struct spawn_cb_arg sca;
if (setsid() == -1 || chdir ("/")) if (setsid() == -1 || chdir ("/"))
_exit (1); _exit (1);
@ -521,9 +579,7 @@ spawn_detached (const char *pgmname, const char *argv[],
if (pid2) if (pid2)
_exit (0); /* Let the parent exit immediately. */ _exit (0); /* Let the parent exit immediately. */
call_spawn_cb (&sca, -1, -1, -1, spawn_cb, spawn_cb_arg); my_exec (pgmname, argv, act);
my_exec (pgmname, argv, &sca);
/*NOTREACHED*/ /*NOTREACHED*/
} }
@ -532,7 +588,7 @@ spawn_detached (const char *pgmname, const char *argv[],
{ {
post_syscall (); post_syscall ();
ec = gpg_err_code_from_syserror (); ec = gpg_err_code_from_syserror ();
log_error ("waitpid failed in gpgrt_spawn_process_detached: %s", log_error ("waitpid failed in spawn_detached: %s",
gpg_strerror (ec)); gpg_strerror (ec));
return ec; return ec;
} }
@ -542,18 +598,9 @@ spawn_detached (const char *pgmname, const char *argv[],
return 0; return 0;
} }
void
gnupg_spawn_helper (struct spawn_cb_arg *sca)
{
int *user_except = sca->arg;
sca->except_fds = user_except;
}
gpg_err_code_t gpg_err_code_t
gnupg_process_spawn (const char *pgmname, const char *argv1[], gnupg_process_spawn (const char *pgmname, const char *argv1[],
unsigned int flags, unsigned int flags, gnupg_spawn_actions_t act,
void (*spawn_cb) (struct spawn_cb_arg *),
void *spawn_cb_arg,
gnupg_process_t *r_process) gnupg_process_t *r_process)
{ {
gpg_err_code_t ec; gpg_err_code_t ec;
@ -564,6 +611,15 @@ gnupg_process_spawn (const char *pgmname, const char *argv1[],
pid_t pid; pid_t pid;
const char **argv; const char **argv;
int i, j; int i, j;
struct gnupg_spawn_actions act_default;
if (!act)
{
memset (&act_default, 0, sizeof (act_default));
for (i = 0; i <= 2; i++)
act_default.fd[i] = -1;
act = &act_default;
}
check_syscall_func (); check_syscall_func ();
@ -603,7 +659,7 @@ gnupg_process_spawn (const char *pgmname, const char *argv1[],
return GPG_ERR_INV_ARG; return GPG_ERR_INV_ARG;
} }
return spawn_detached (pgmname, argv, spawn_cb, spawn_cb_arg); return spawn_detached (pgmname, argv, act);
} }
process = xtrycalloc (1, sizeof (struct gnupg_process)); process = xtrycalloc (1, sizeof (struct gnupg_process));
@ -732,8 +788,6 @@ gnupg_process_spawn (const char *pgmname, const char *argv1[],
if (!pid) if (!pid)
{ {
struct spawn_cb_arg sca;
if (fd_in[1] >= 0) if (fd_in[1] >= 0)
close (fd_in[1]); close (fd_in[1]);
if (fd_out[0] >= 0) if (fd_out[0] >= 0)
@ -741,11 +795,15 @@ gnupg_process_spawn (const char *pgmname, const char *argv1[],
if (fd_err[0] >= 0) if (fd_err[0] >= 0)
close (fd_err[0]); close (fd_err[0]);
call_spawn_cb (&sca, fd_in[0], fd_out[1], fd_err[1], if (act->fd[0] < 0)
spawn_cb, spawn_cb_arg); act->fd[0] = fd_in[0];
if (act->fd[1] < 0)
act->fd[1] = fd_out[1];
if (act->fd[2] < 0)
act->fd[2] = fd_err[1];
/* Run child. */ /* Run child. */
my_exec (pgmname, argv, &sca); my_exec (pgmname, argv, act);
/*NOTREACHED*/ /*NOTREACHED*/
} }

View File

@ -65,7 +65,6 @@
#include "util.h" #include "util.h"
#include "i18n.h" #include "i18n.h"
#include "sysutils.h" #include "sysutils.h"
#define NEED_STRUCT_SPAWN_CB_ARG
#include "exechelp.h" #include "exechelp.h"
#include <windows.h> #include <windows.h>
@ -126,7 +125,7 @@ get_max_fds (void)
/* Under Windows this is a dummy function. */ /* Under Windows this is a dummy function. */
void void
close_all_fds (int first, int *except) close_all_fds (int first, const int *except)
{ {
(void)first; (void)first;
(void)except; (void)except;
@ -410,6 +409,12 @@ gnupg_close_pipe (int fd)
close (fd); close (fd);
} }
struct gnupg_spawn_actions {
void *hd[3];
void **inherit_hds;
char *env;
};
struct gnupg_process { struct gnupg_process {
const char *pgmname; const char *pgmname;
unsigned int terminated :1; /* or detached */ unsigned int terminated :1; /* or detached */
@ -479,8 +484,7 @@ check_windows_version (void)
static gpg_err_code_t static gpg_err_code_t
spawn_detached (const char *pgmname, char *cmdline, spawn_detached (const char *pgmname, char *cmdline, gnupg_spawn_actions_t act)
void (*spawn_cb) (struct spawn_cb_arg *), void *spawn_cb_arg)
{ {
SECURITY_ATTRIBUTES sec_attr; SECURITY_ATTRIBUTES sec_attr;
PROCESS_INFORMATION pi = { NULL, 0, 0, 0 }; PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
@ -490,8 +494,8 @@ spawn_detached (const char *pgmname, char *cmdline,
wchar_t *wpgmname = NULL; wchar_t *wpgmname = NULL;
gpg_err_code_t ec; gpg_err_code_t ec;
int ret; int ret;
struct spawn_cb_arg sca;
BOOL ask_inherit = FALSE; BOOL ask_inherit = FALSE;
int i;
ec = gnupg_access (pgmname, X_OK); ec = gnupg_access (pgmname, X_OK);
if (ec) if (ec)
@ -502,22 +506,27 @@ spawn_detached (const char *pgmname, char *cmdline,
memset (&si, 0, sizeof si); memset (&si, 0, sizeof si);
sca.allow_foreground_window = FALSE; i = 0;
sca.hd[0] = INVALID_HANDLE_VALUE; if (act->hd[0] != INVALID_HANDLE_VALUE)
sca.hd[1] = INVALID_HANDLE_VALUE; i++;
sca.hd[2] = INVALID_HANDLE_VALUE; if (act->hd[1] != INVALID_HANDLE_VALUE)
sca.inherit_hds = NULL; i++;
sca.arg = spawn_cb_arg; if (act->hd[2] != INVALID_HANDLE_VALUE)
if (spawn_cb) i++;
(*spawn_cb) (&sca);
if (sca.inherit_hds) if (i != 0 || act->inherit_hds)
{ {
SIZE_T attr_list_size = 0; SIZE_T attr_list_size = 0;
HANDLE hd[16]; HANDLE hd[16];
HANDLE *hd_p = sca.inherit_hds; HANDLE *hd_p = act->inherit_hds;
int j = 0; int j = 0;
if (act->hd[0] != INVALID_HANDLE_VALUE)
hd[j++] = act->hd[0];
if (act->hd[1] != INVALID_HANDLE_VALUE)
hd[j++] = act->hd[1];
if (act->hd[1] != INVALID_HANDLE_VALUE)
hd[j++] = act->hd[2];
if (hd_p) if (hd_p)
{ {
while (*hd_p != INVALID_HANDLE_VALUE) while (*hd_p != INVALID_HANDLE_VALUE)
@ -559,7 +568,8 @@ spawn_detached (const char *pgmname, char *cmdline,
/* Start the process. */ /* Start the process. */
si.StartupInfo.cb = sizeof (si); si.StartupInfo.cb = sizeof (si);
si.StartupInfo.dwFlags = STARTF_USESHOWWINDOW; si.StartupInfo.dwFlags = ((i > 0 ? STARTF_USESTDHANDLES : 0)
| STARTF_USESHOWWINDOW);
si.StartupInfo.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE; si.StartupInfo.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
cr_flags = (CREATE_DEFAULT_ERROR_MODE cr_flags = (CREATE_DEFAULT_ERROR_MODE
@ -579,7 +589,7 @@ spawn_detached (const char *pgmname, char *cmdline,
&sec_attr, /* Thread security attributes. */ &sec_attr, /* Thread security attributes. */
ask_inherit, /* Inherit handles. */ ask_inherit, /* Inherit handles. */
cr_flags, /* Creation flags. */ cr_flags, /* Creation flags. */
NULL, /* Environment. */ act->env, /* Environment. */
NULL, /* Use current drive/directory. */ NULL, /* Use current drive/directory. */
(STARTUPINFOW *)&si, /* Startup information. */ (STARTUPINFOW *)&si, /* Startup information. */
&pi /* Returns process information. */ &pi /* Returns process information. */
@ -617,18 +627,60 @@ spawn_detached (const char *pgmname, char *cmdline,
} }
void gpg_err_code_t
gnupg_spawn_helper (struct spawn_cb_arg *sca) gnupg_spawn_actions_new (gnupg_spawn_actions_t *r_act)
{ {
HANDLE *user_except = sca->arg; gnupg_spawn_actions_t act;
sca->inherit_hds = user_except; int i;
*r_act = NULL;
act = xtrycalloc (1, sizeof (struct gnupg_spawn_actions));
if (act == NULL)
return gpg_err_code_from_syserror ();
for (i = 0; i <= 2; i++)
act->hd[i] = INVALID_HANDLE_VALUE;
*r_act = act;
return 0;
} }
void
gnupg_spawn_actions_release (gnupg_spawn_actions_t act)
{
if (!act)
return;
xfree (act);
}
void
gnupg_spawn_actions_set_envvars (gnupg_spawn_actions_t act, char *env)
{
act->env = env;
}
void
gnupg_spawn_actions_set_redirect (gnupg_spawn_actions_t act,
void *in, void *out, void *err)
{
act->hd[0] = in;
act->hd[1] = out;
act->hd[2] = err;
}
void
gnupg_spawn_actions_set_inherit_handles (gnupg_spawn_actions_t act,
void **handles)
{
act->inherit_hds = handles;
}
gpg_err_code_t gpg_err_code_t
gnupg_process_spawn (const char *pgmname, const char *argv[], gnupg_process_spawn (const char *pgmname, const char *argv[],
unsigned int flags, unsigned int flags, gnupg_spawn_actions_t act,
void (*spawn_cb) (struct spawn_cb_arg *),
void *spawn_cb_arg,
gnupg_process_t *r_process) gnupg_process_t *r_process)
{ {
gpg_err_code_t ec; gpg_err_code_t ec;
@ -644,9 +696,18 @@ gnupg_process_spawn (const char *pgmname, const char *argv[],
HANDLE hd_in[2]; HANDLE hd_in[2];
HANDLE hd_out[2]; HANDLE hd_out[2];
HANDLE hd_err[2]; HANDLE hd_err[2];
struct spawn_cb_arg sca;
int i; int i;
BOOL ask_inherit = FALSE; BOOL ask_inherit = FALSE;
BOOL allow_foreground_window = FALSE;
struct gnupg_spawn_actions act_default;
if (!act)
{
memset (&act_default, 0, sizeof (act_default));
for (i = 0; i <= 2; i++)
act_default.hd[i] = INVALID_HANDLE_VALUE;
act = &act_default;
}
check_syscall_func (); check_syscall_func ();
@ -670,7 +731,7 @@ gnupg_process_spawn (const char *pgmname, const char *argv[],
return GPG_ERR_INV_ARG; return GPG_ERR_INV_ARG;
} }
return spawn_detached (pgmname, cmdline, spawn_cb, spawn_cb_arg); return spawn_detached (pgmname, cmdline, act);
} }
if (r_process) if (r_process)
@ -770,36 +831,34 @@ gnupg_process_spawn (const char *pgmname, const char *argv[],
memset (&si, 0, sizeof si); memset (&si, 0, sizeof si);
sca.allow_foreground_window = FALSE; if (act->hd[0] == INVALID_HANDLE_VALUE)
sca.hd[0] = hd_in[0]; act->hd[0] = hd_in[0];
sca.hd[1] = hd_out[1]; if (act->hd[1] == INVALID_HANDLE_VALUE)
sca.hd[2] = hd_err[1]; act->hd[1] = hd_out[1];
sca.inherit_hds = NULL; if (act->hd[2] == INVALID_HANDLE_VALUE)
sca.arg = spawn_cb_arg; act->hd[2] = hd_err[1];
if (spawn_cb)
(*spawn_cb) (&sca);
i = 0; i = 0;
if (sca.hd[0] != INVALID_HANDLE_VALUE) if (act->hd[0] != INVALID_HANDLE_VALUE)
i++; i++;
if (sca.hd[1] != INVALID_HANDLE_VALUE) if (act->hd[1] != INVALID_HANDLE_VALUE)
i++; i++;
if (sca.hd[2] != INVALID_HANDLE_VALUE) if (act->hd[2] != INVALID_HANDLE_VALUE)
i++; i++;
if (i != 0 || sca.inherit_hds) if (i != 0 || act->inherit_hds)
{ {
SIZE_T attr_list_size = 0; SIZE_T attr_list_size = 0;
HANDLE hd[16]; HANDLE hd[16];
HANDLE *hd_p = sca.inherit_hds; HANDLE *hd_p = act->inherit_hds;
int j = 0; int j = 0;
if (sca.hd[0] != INVALID_HANDLE_VALUE) if (act->hd[0] != INVALID_HANDLE_VALUE)
hd[j++] = sca.hd[0]; hd[j++] = act->hd[0];
if (sca.hd[1] != INVALID_HANDLE_VALUE) if (act->hd[1] != INVALID_HANDLE_VALUE)
hd[j++] = sca.hd[1]; hd[j++] = act->hd[1];
if (sca.hd[1] != INVALID_HANDLE_VALUE) if (act->hd[1] != INVALID_HANDLE_VALUE)
hd[j++] = sca.hd[2]; hd[j++] = act->hd[2];
if (hd_p) if (hd_p)
{ {
while (*hd_p != INVALID_HANDLE_VALUE) while (*hd_p != INVALID_HANDLE_VALUE)
@ -858,9 +917,9 @@ gnupg_process_spawn (const char *pgmname, const char *argv[],
si.StartupInfo.cb = sizeof (si); si.StartupInfo.cb = sizeof (si);
si.StartupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.StartupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.StartupInfo.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_HIDE; si.StartupInfo.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_HIDE;
si.StartupInfo.hStdInput = sca.hd[0]; si.StartupInfo.hStdInput = act->hd[0];
si.StartupInfo.hStdOutput = sca.hd[1]; si.StartupInfo.hStdOutput = act->hd[1];
si.StartupInfo.hStdError = sca.hd[2]; si.StartupInfo.hStdError = act->hd[2];
/* log_debug ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline); */ /* log_debug ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline); */
cr_flags = (CREATE_DEFAULT_ERROR_MODE cr_flags = (CREATE_DEFAULT_ERROR_MODE
@ -877,9 +936,9 @@ gnupg_process_spawn (const char *pgmname, const char *argv[],
&sec_attr, /* Thread security attributes. */ &sec_attr, /* Thread security attributes. */
ask_inherit, /* Inherit handles. */ ask_inherit, /* Inherit handles. */
cr_flags, /* Creation flags. */ cr_flags, /* Creation flags. */
NULL, /* Environment. */ act->env, /* Environment. */
NULL, /* Use current drive/directory. */ NULL, /* Use current drive/directory. */
(STARTUPINFOW *)&si, /* Startup information. */ (STARTUPINFOW *)&si, /* Startup information. */
&pi /* Returns process information. */ &pi /* Returns process information. */
); );
if (!ret) if (!ret)
@ -933,7 +992,7 @@ gnupg_process_spawn (const char *pgmname, const char *argv[],
/* pi.hProcess, pi.hThread, */ /* pi.hProcess, pi.hThread, */
/* (int) pi.dwProcessId, (int) pi.dwThreadId); */ /* (int) pi.dwProcessId, (int) pi.dwThreadId); */
if (sca.allow_foreground_window) if (allow_foreground_window)
{ {
/* Fixme: For unknown reasons AllowSetForegroundWindow returns /* Fixme: For unknown reasons AllowSetForegroundWindow returns
* an invalid argument error if we pass it the correct * an invalid argument error if we pass it the correct

View File

@ -42,7 +42,7 @@ int get_max_fds (void);
EXCEPT is not NULL, it is expected to be a list of file descriptors EXCEPT is not NULL, it is expected to be a list of file descriptors
which are not to close. This list shall be sorted in ascending which are not to close. This list shall be sorted in ascending
order with its end marked by -1. */ order with its end marked by -1. */
void close_all_fds (int first, int *except); void close_all_fds (int first, const int *except);
/* Returns an array with all currently open file descriptors. The end /* Returns an array with all currently open file descriptors. The end
@ -75,22 +75,21 @@ void gnupg_close_pipe (int fd);
/* The opaque type for a subprocess. */ /* The opaque type for a subprocess. */
typedef struct gnupg_process *gnupg_process_t; typedef struct gnupg_process *gnupg_process_t;
typedef struct gnupg_spawn_actions *gnupg_spawn_actions_t;
gpg_err_code_t gnupg_spawn_actions_new (gnupg_spawn_actions_t *r_act);
void gnupg_spawn_actions_release (gnupg_spawn_actions_t act);
#ifdef HAVE_W32_SYSTEM #ifdef HAVE_W32_SYSTEM
struct spawn_cb_arg; void gnupg_spawn_actions_set_envvars (gnupg_spawn_actions_t, char *);
#ifdef NEED_STRUCT_SPAWN_CB_ARG void gnupg_spawn_actions_set_redirect (gnupg_spawn_actions_t,
struct spawn_cb_arg { void *, void *, void *);
HANDLE hd[3]; void gnupg_spawn_actions_set_inherit_handles (gnupg_spawn_actions_t, void **);
HANDLE *inherit_hds;
BOOL allow_foreground_window;
void *arg;
};
#endif
#else #else
struct spawn_cb_arg { void gnupg_spawn_actions_set_environ (gnupg_spawn_actions_t, char **);
int fds[3]; void gnupg_spawn_actions_set_redirect (gnupg_spawn_actions_t, int, int, int);
int *except_fds; void gnupg_spawn_actions_set_inherit_fds (gnupg_spawn_actions_t,
void *arg; const int *);
}; void gnupg_spawn_actions_set_atfork (gnupg_spawn_actions_t,
void (*atfork)(void *), void *arg);
#endif #endif
#define GNUPG_PROCESS_DETACHED (1 << 1) #define GNUPG_PROCESS_DETACHED (1 << 1)
@ -110,14 +109,10 @@ struct spawn_cb_arg {
#define GNUPG_PROCESS_STREAM_NONBLOCK (1 << 16) #define GNUPG_PROCESS_STREAM_NONBLOCK (1 << 16)
/* Spawn helper. */
void gnupg_spawn_helper (struct spawn_cb_arg *sca);
/* Spawn PGMNAME. */ /* Spawn PGMNAME. */
gpg_err_code_t gnupg_process_spawn (const char *pgmname, const char *argv[], gpg_err_code_t gnupg_process_spawn (const char *pgmname, const char *argv1[],
unsigned int flags, unsigned int flags,
void (*spawn_cb) (struct spawn_cb_arg *), gnupg_spawn_actions_t act,
void *spawn_cb_arg,
gnupg_process_t *r_process); gnupg_process_t *r_process);
/* Get FDs for subprocess I/O. It is the caller which should care /* Get FDs for subprocess I/O. It is the caller which should care

View File

@ -338,6 +338,7 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
read_and_log_buffer_t fderrstate; read_and_log_buffer_t fderrstate;
struct copy_buffer *cpbuf_in = NULL, *cpbuf_out = NULL, *cpbuf_extra = NULL; struct copy_buffer *cpbuf_in = NULL, *cpbuf_out = NULL, *cpbuf_extra = NULL;
int quiet = 0; int quiet = 0;
gnupg_spawn_actions_t act = NULL;
memset (fds, 0, sizeof fds); memset (fds, 0, sizeof fds);
memset (&fderrstate, 0, sizeof fderrstate); memset (&fderrstate, 0, sizeof fderrstate);
@ -413,13 +414,21 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
else else
exceptclose[0] = -1; exceptclose[0] = -1;
err = gnupg_spawn_actions_new (&act);
if (err)
goto leave;
#ifdef HAVE_W32_SYSTEM
gnupg_spawn_actions_set_inherit_handles (act, exceptclose);
#else
gnupg_spawn_actions_set_inherit_fds (act, exceptclose);
#endif
err = gnupg_process_spawn (pgmname, argv, err = gnupg_process_spawn (pgmname, argv,
((input ((input
? GNUPG_PROCESS_STDIN_PIPE ? GNUPG_PROCESS_STDIN_PIPE
: 0) : 0)
| GNUPG_PROCESS_STDOUT_PIPE | GNUPG_PROCESS_STDOUT_PIPE
| GNUPG_PROCESS_STDERR_PIPE), | GNUPG_PROCESS_STDERR_PIPE), act, &proc);
gnupg_spawn_helper, exceptclose, &proc);
gnupg_process_get_streams (proc, GNUPG_PROCESS_STREAM_NONBLOCK, gnupg_process_get_streams (proc, GNUPG_PROCESS_STREAM_NONBLOCK,
input? &infp : NULL, &outfp, &errfp); input? &infp : NULL, &outfp, &errfp);
if (extrapipe[0] != -1) if (extrapipe[0] != -1)
@ -572,6 +581,7 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
es_fclose (outfp); es_fclose (outfp);
es_fclose (errfp); es_fclose (errfp);
gnupg_process_release (proc); gnupg_process_release (proc);
gnupg_spawn_actions_release (act);
copy_buffer_shred (cpbuf_in); copy_buffer_shred (cpbuf_in);
xfree (cpbuf_in); xfree (cpbuf_in);

View File

@ -266,7 +266,7 @@ test_pipe_stream (const char *pgmname)
err = gnupg_process_spawn (pgmname, argv, err = gnupg_process_spawn (pgmname, argv,
(GNUPG_PROCESS_STDOUT_PIPE (GNUPG_PROCESS_STDOUT_PIPE
|GNUPG_PROCESS_STDERR_KEEP), |GNUPG_PROCESS_STDERR_KEEP),
NULL, NULL, &proc); NULL, &proc);
if (err) if (err)
{ {
fprintf (stderr, "gnupg_process_spawn failed\n"); fprintf (stderr, "gnupg_process_spawn failed\n");

View File

@ -851,7 +851,7 @@ ldap_wrapper (ctrl_t ctrl, ksba_reader_t *reader, const char *argv[])
err = gnupg_process_spawn (pgmname, arg_list, err = gnupg_process_spawn (pgmname, arg_list,
(GNUPG_PROCESS_STDOUT_PIPE (GNUPG_PROCESS_STDOUT_PIPE
| GNUPG_PROCESS_STDERR_PIPE), | GNUPG_PROCESS_STDERR_PIPE),
NULL, NULL, &process); NULL, &process);
if (err) if (err)
{ {
xfree (arg_list); xfree (arg_list);

View File

@ -601,7 +601,7 @@ run_with_pipe (struct spawn_info *info, const void *image, u32 len)
fill_command_argv (argv, info->command); fill_command_argv (argv, info->command);
err = gnupg_process_spawn (argv[0], argv+1, GNUPG_PROCESS_STDIN_PIPE, err = gnupg_process_spawn (argv[0], argv+1, GNUPG_PROCESS_STDIN_PIPE,
NULL, NULL, &proc); NULL, &proc);
if (err) if (err)
log_error (_("unable to execute shell '%s': %s\n"), log_error (_("unable to execute shell '%s': %s\n"),
argv[0], gpg_strerror (err)); argv[0], gpg_strerror (err));
@ -695,7 +695,7 @@ show_photo (const char *command, const char *name, const void *image, u32 len)
const char *argv[4]; const char *argv[4];
fill_command_argv (argv, spawn->command); fill_command_argv (argv, spawn->command);
err = gnupg_process_spawn (argv[0], argv+1, 0, NULL, NULL, NULL); err = gnupg_process_spawn (argv[0], argv+1, 0, NULL, NULL);
if (err) if (err)
log_error (_("unnatural exit of external program\n")); log_error (_("unnatural exit of external program\n"));
#endif #endif

View File

@ -2383,18 +2383,15 @@ app_check_pin (card_t card, ctrl_t ctrl, const char *keyidstr,
return err; return err;
} }
#ifndef HAVE_W32_SYSTEM
static void static void
setup_env (struct spawn_cb_arg *sca) setup_env (void *arg)
{ {
#ifdef HAVE_W32_SYSTEM char *v = arg;
(void)sca; /* Not supported on Windows. */
#else
char *v = sca->arg;
putenv (v); putenv (v);
#endif
} }
#endif
static void static void
report_change (int slot, int old_status, int cur_status) report_change (int slot, int old_status, int cur_status)
@ -2425,6 +2422,7 @@ report_change (int slot, int old_status, int cur_status)
gpg_error_t err; gpg_error_t err;
const char *args[9]; const char *args[9];
char numbuf1[30], numbuf2[30], numbuf3[30]; char numbuf1[30], numbuf2[30], numbuf3[30];
gnupg_spawn_actions_t act = NULL;
sprintf (numbuf1, "%d", slot); sprintf (numbuf1, "%d", slot);
sprintf (numbuf2, "0x%04X", old_status); sprintf (numbuf2, "0x%04X", old_status);
@ -2442,9 +2440,16 @@ report_change (int slot, int old_status, int cur_status)
args[8] = NULL; args[8] = NULL;
fname = make_filename (gnupg_homedir (), "scd-event", NULL); fname = make_filename (gnupg_homedir (), "scd-event", NULL);
err = gnupg_process_spawn (fname, args, err = gnupg_spawn_actions_new (&act);
GNUPG_PROCESS_DETACHED, if (!err)
setup_env, envstr, NULL); {
#ifndef HAVE_W32_SYSTEM
gnupg_spawn_actions_set_atfork (act, setup_env, envstr);
#endif
err = gnupg_process_spawn (fname, args, GNUPG_PROCESS_DETACHED,
act, NULL);
gnupg_spawn_actions_release (act);
}
if (err && gpg_err_code (err) != GPG_ERR_ENOENT) if (err && gpg_err_code (err) != GPG_ERR_ENOENT)
log_error ("failed to run event handler '%s': %s\n", log_error ("failed to run event handler '%s': %s\n",
fname, gpg_strerror (err)); fname, gpg_strerror (err));

View File

@ -938,7 +938,7 @@ do_process_spawn_io (scheme *sc, pointer args)
} }
err = gnupg_process_spawn (argv[0], (const char **) &argv[1], err = gnupg_process_spawn (argv[0], (const char **) &argv[1],
flags, NULL, NULL, &proc); flags, NULL, &proc);
err = gnupg_process_get_streams (proc, 0, &infp, NULL, NULL); err = gnupg_process_get_streams (proc, 0, &infp, NULL, NULL);
err = es_write (infp, a_input, strlen (a_input), NULL); err = es_write (infp, a_input, strlen (a_input), NULL);
@ -1137,25 +1137,6 @@ do_process_spawn_io (scheme *sc, pointer args)
FFI_RETURN_ERR (sc, err); FFI_RETURN_ERR (sc, err);
} }
static void
setup_std_fds (struct spawn_cb_arg *sca)
{
int *std_fds = sca->arg;
#ifdef HAVE_W32_SYSTEM
sca->hd[0] = std_fds[0] == -1?
INVALID_HANDLE_VALUE : (HANDLE)_get_osfhandle (std_fds[0]);
sca->hd[1] = std_fds[1] == -1?
INVALID_HANDLE_VALUE : (HANDLE)_get_osfhandle (std_fds[1]);
sca->hd[2] = std_fds[2] == -1?
INVALID_HANDLE_VALUE : (HANDLE)_get_osfhandle (std_fds[2]);
#else
sca->fds[0] = std_fds[0];
sca->fds[1] = std_fds[1];
sca->fds[2] = std_fds[2];
#endif
}
static pointer static pointer
do_process_spawn_fd (scheme *sc, pointer args) do_process_spawn_fd (scheme *sc, pointer args)
{ {
@ -1165,6 +1146,7 @@ do_process_spawn_fd (scheme *sc, pointer args)
size_t len; size_t len;
int std_fds[3]; int std_fds[3];
gnupg_process_t proc = NULL; gnupg_process_t proc = NULL;
gnupg_spawn_actions_t act = NULL;
FFI_ARG_OR_RETURN (sc, pointer, arguments, list, args); FFI_ARG_OR_RETURN (sc, pointer, arguments, list, args);
FFI_ARG_OR_RETURN (sc, int, std_fds[0], number, args); FFI_ARG_OR_RETURN (sc, int, std_fds[0], number, args);
@ -1189,8 +1171,35 @@ do_process_spawn_fd (scheme *sc, pointer args)
fprintf (stderr, " (%d %d %d)\n", std_fds[0], std_fds[1], std_fds[2]); fprintf (stderr, " (%d %d %d)\n", std_fds[0], std_fds[1], std_fds[2]);
} }
err = gnupg_process_spawn (argv[0], (const char **) &argv[1], err = gnupg_spawn_actions_new (&act);
0, setup_std_fds, std_fds, &proc); if (err)
{
FFI_RETURN_ERR (sc, err);
}
#ifdef HAVE_W32_SYSTEM
{
HANDLE std_in, std_out, std_err;
if (std_fds[0] == -1)
std_in = INVALID_HANDLE_VALUE;
else
std_in = (HANDLE)_get_osfhandle (std_fds[0]);
if (std_fds[1] == -1)
std_out = INVALID_HANDLE_VALUE;
else
std_out = (HANDLE)_get_osfhandle (std_fds[1]);
if (std_fds[2] == -1)
std_err = INVALID_HANDLE_VALUE;
else
std_err = (HANDLE)_get_osfhandle (std_fds[2]);
gnupg_spawn_actions_set_redirect (act, std_in, std_out, std_err);
}
#else
gnupg_spawn_actions_set_redirect (act, std_fds[0], std_fds[1], std_fds[2]);
#endif
err = gnupg_process_spawn (argv[0], (const char **)&argv[1], 0, act, &proc);
gnupg_spawn_actions_release (act);
xfree (argv); xfree (argv);
FFI_RETURN_POINTER (sc, proc_wrap (sc, proc)); FFI_RETURN_POINTER (sc, proc_wrap (sc, proc));
} }

View File

@ -3835,7 +3835,7 @@ cmd_gpg (card_info_t info, char *argstr, int use_gpgsm)
argv, argv,
(GNUPG_PROCESS_STDOUT_KEEP (GNUPG_PROCESS_STDOUT_KEEP
| GNUPG_PROCESS_STDERR_KEEP), | GNUPG_PROCESS_STDERR_KEEP),
NULL, NULL, &proc); NULL, &proc);
if (!err) if (!err)
{ {
err = gnupg_process_wait (proc, 1); err = gnupg_process_wait (proc, 1);

View File

@ -761,7 +761,7 @@ gpg_agent_runtime_change (int killflag)
log_assert (i < DIM(argv)); log_assert (i < DIM(argv));
if (!err) if (!err)
err = gnupg_process_spawn (pgmname, argv, 0, NULL, NULL, &proc); err = gnupg_process_spawn (pgmname, argv, 0, NULL, &proc);
if (!err) if (!err)
err = gnupg_process_wait (proc, 1); err = gnupg_process_wait (proc, 1);
if (err) if (err)
@ -805,7 +805,7 @@ scdaemon_runtime_change (int killflag)
log_assert (i < DIM(argv)); log_assert (i < DIM(argv));
if (!err) if (!err)
err = gnupg_process_spawn (pgmname, argv, 0, NULL, NULL, &proc); err = gnupg_process_spawn (pgmname, argv, 0, NULL, &proc);
if (!err) if (!err)
err = gnupg_process_wait (proc, 1); err = gnupg_process_wait (proc, 1);
if (err) if (err)
@ -850,7 +850,7 @@ tpm2daemon_runtime_change (int killflag)
log_assert (i < DIM(argv)); log_assert (i < DIM(argv));
if (!err) if (!err)
err = gnupg_process_spawn (pgmname, argv, 0, NULL, NULL, &proc); err = gnupg_process_spawn (pgmname, argv, 0, NULL, &proc);
if (!err) if (!err)
err = gnupg_process_wait (proc, 1); err = gnupg_process_wait (proc, 1);
if (err) if (err)
@ -885,7 +885,7 @@ dirmngr_runtime_change (int killflag)
log_assert (i < DIM(argv)); log_assert (i < DIM(argv));
if (!err) if (!err)
err = gnupg_process_spawn (pgmname, argv, 0, NULL, NULL, &proc); err = gnupg_process_spawn (pgmname, argv, 0, NULL, &proc);
if (!err) if (!err)
err = gnupg_process_wait (proc, 1); err = gnupg_process_wait (proc, 1);
if (err) if (err)
@ -919,7 +919,7 @@ keyboxd_runtime_change (int killflag)
log_assert (i < DIM(argv)); log_assert (i < DIM(argv));
if (!err) if (!err)
err = gnupg_process_spawn (pgmname, argv, 0, NULL, NULL, &proc); err = gnupg_process_spawn (pgmname, argv, 0, NULL, &proc);
if (!err) if (!err)
err = gnupg_process_wait (proc, 1); err = gnupg_process_wait (proc, 1);
if (err) if (err)
@ -985,7 +985,7 @@ gc_component_launch (int component)
argv[i] = NULL; argv[i] = NULL;
log_assert (i < DIM(argv)); log_assert (i < DIM(argv));
err = gnupg_process_spawn (pgmname, argv, 0, NULL, NULL, &proc); err = gnupg_process_spawn (pgmname, argv, 0, NULL, &proc);
if (!err) if (!err)
err = gnupg_process_wait (proc, 1); err = gnupg_process_wait (proc, 1);
if (err) if (err)
@ -1369,9 +1369,8 @@ gc_component_check_options (int component, estream_t out, const char *conf_file)
result = 0; result = 0;
errlines = NULL; errlines = NULL;
err = gnupg_process_spawn (pgmname, argv, err = gnupg_process_spawn (pgmname, argv, GNUPG_PROCESS_STDERR_PIPE,
GNUPG_PROCESS_STDERR_PIPE, NULL, &proc);
NULL, NULL, &proc);
if (err) if (err)
result |= 1; /* Program could not be run. */ result |= 1; /* Program could not be run. */
else else
@ -1763,9 +1762,8 @@ retrieve_options_from_program (gc_component_id_t component, int only_installed)
/* First we need to read the option table from the program. */ /* First we need to read the option table from the program. */
argv[0] = "--dump-option-table"; argv[0] = "--dump-option-table";
argv[1] = NULL; argv[1] = NULL;
err = gnupg_process_spawn (pgmname, argv, err = gnupg_process_spawn (pgmname, argv, GNUPG_PROCESS_STDOUT_PIPE,
GNUPG_PROCESS_STDOUT_PIPE, NULL, &proc);
NULL, NULL, &proc);
if (err) if (err)
{ {
gc_error (1, 0, "could not gather option table from '%s': %s", gc_error (1, 0, "could not gather option table from '%s': %s",
@ -1952,9 +1950,8 @@ retrieve_options_from_program (gc_component_id_t component, int only_installed)
/* Now read the default options. */ /* Now read the default options. */
argv[0] = "--gpgconf-list"; argv[0] = "--gpgconf-list";
argv[1] = NULL; argv[1] = NULL;
err = gnupg_process_spawn (pgmname, argv, err = gnupg_process_spawn (pgmname, argv, GNUPG_PROCESS_STDOUT_PIPE,
GNUPG_PROCESS_STDOUT_PIPE, NULL, &proc);
NULL, NULL, &proc);
if (err) if (err)
{ {
gc_error (1, 0, "could not gather active options from '%s': %s", gc_error (1, 0, "could not gather active options from '%s': %s",

View File

@ -1311,9 +1311,8 @@ show_versions_via_dirmngr (estream_t fp)
pgmname = gnupg_module_name (GNUPG_MODULE_NAME_DIRMNGR); pgmname = gnupg_module_name (GNUPG_MODULE_NAME_DIRMNGR);
argv[0] = "--gpgconf-versions"; argv[0] = "--gpgconf-versions";
argv[1] = NULL; argv[1] = NULL;
err = gnupg_process_spawn (pgmname, argv, err = gnupg_process_spawn (pgmname, argv, GNUPG_PROCESS_STDOUT_PIPE,
GNUPG_PROCESS_STDOUT_PIPE, NULL, &proc);
NULL, NULL, &proc);
if (err) if (err)
{ {
log_error ("error spawning %s: %s", pgmname, gpg_strerror (err)); log_error ("error spawning %s: %s", pgmname, gpg_strerror (err));

View File

@ -1234,6 +1234,7 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names,
int except[2] = { -1, -1 }; int except[2] = { -1, -1 };
#endif #endif
const char **argv; const char **argv;
gnupg_spawn_actions_t act = NULL;
/* '--encrypt' may be combined with '--symmetric', but 'encrypt' /* '--encrypt' may be combined with '--symmetric', but 'encrypt'
* is set either way. Clear it if no recipients are specified. * is set either way. Clear it if no recipients are specified.
@ -1296,11 +1297,23 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names,
goto leave; goto leave;
} }
err = gnupg_spawn_actions_new (&act);
if (err)
{
xfree (argv);
goto leave;
}
#ifdef HAVE_W32_SYSTEM
gnupg_spawn_actions_set_inherit_handles (act, except);
#else
gnupg_spawn_actions_set_inherit_fds (act, except);
#endif
err = gnupg_process_spawn (opt.gpg_program, argv, err = gnupg_process_spawn (opt.gpg_program, argv,
(GNUPG_PROCESS_STDIN_PIPE (GNUPG_PROCESS_STDIN_PIPE
| GNUPG_PROCESS_STDOUT_KEEP | GNUPG_PROCESS_STDOUT_KEEP
| GNUPG_PROCESS_STDERR_KEEP), | GNUPG_PROCESS_STDERR_KEEP), act, &proc);
gnupg_spawn_helper, except, &proc); gnupg_spawn_actions_release (act);
xfree (argv); xfree (argv);
if (err) if (err)
goto leave; goto leave;

View File

@ -390,6 +390,7 @@ gpgtar_extract (const char *filename, int decrypt)
int except[2] = { -1, -1 }; int except[2] = { -1, -1 };
#endif #endif
const char **argv; const char **argv;
gnupg_spawn_actions_t act = NULL;
ccparray_init (&ccp, 0); ccparray_init (&ccp, 0);
if (opt.batch) if (opt.batch)
@ -435,10 +436,22 @@ gpgtar_extract (const char *filename, int decrypt)
goto leave; goto leave;
} }
err = gnupg_spawn_actions_new (&act);
if (err)
{
xfree (argv);
goto leave;
}
#ifdef HAVE_W32_SYSTEM
gnupg_spawn_actions_set_inherit_handles (act, except);
#else
gnupg_spawn_actions_set_inherit_fds (act, except);
#endif
err = gnupg_process_spawn (opt.gpg_program, argv, err = gnupg_process_spawn (opt.gpg_program, argv,
((filename ? 0 : GNUPG_PROCESS_STDIN_KEEP) ((filename ? 0 : GNUPG_PROCESS_STDIN_KEEP)
| GNUPG_PROCESS_STDOUT_PIPE), | GNUPG_PROCESS_STDOUT_PIPE), act, &proc);
gnupg_spawn_helper, except, &proc); gnupg_spawn_actions_release (act);
xfree (argv); xfree (argv);
if (err) if (err)
goto leave; goto leave;

View File

@ -474,6 +474,7 @@ gpgtar_list (const char *filename, int decrypt)
int except[2] = { -1, -1 }; int except[2] = { -1, -1 };
#endif #endif
const char **argv; const char **argv;
gnupg_spawn_actions_t act = NULL;
ccparray_init (&ccp, 0); ccparray_init (&ccp, 0);
if (opt.batch) if (opt.batch)
@ -513,10 +514,22 @@ gpgtar_list (const char *filename, int decrypt)
goto leave; goto leave;
} }
err = gnupg_spawn_actions_new (&act);
if (err)
{
xfree (argv);
goto leave;
}
#ifdef HAVE_W32_SYSTEM
gnupg_spawn_actions_set_inherit_handles (act, except);
#else
gnupg_spawn_actions_set_inherit_fds (act, except);
#endif
err = gnupg_process_spawn (opt.gpg_program, argv, err = gnupg_process_spawn (opt.gpg_program, argv,
((filename ? 0 : GNUPG_PROCESS_STDIN_KEEP) ((filename ? 0 : GNUPG_PROCESS_STDIN_KEEP)
| GNUPG_PROCESS_STDOUT_PIPE), | GNUPG_PROCESS_STDOUT_PIPE), act, &proc);
gnupg_spawn_helper, except, &proc); gnupg_spawn_actions_release (act);
xfree (argv); xfree (argv);
if (err) if (err)
goto leave; goto leave;