common,agent,gpg,dirmngr,g13,scd,tests,tools: New spawn function.

* common/exechelp-posix.c (do_exec, gnupg_spawn_process): Remove.
(check_syscall_func, pre_syscall, post_syscall) : New.
(do_create_socketpair, posix_open_null, call_spawn_cb): New.
(my_exec, spawn_detached, gnupg_spawn_helper): New.
(gnupg_process_spawn, process_kill, gnupg_process_terminate): New.
(gnupg_process_get_fds, gnupg_process_get_streams): New.
(process_vctl, gnupg_process_ctl): New.
(gnupg_process_wait, gnupg_process_release): New.
(gnupg_process_wait_list): New.
* common/exechelp-w32.c: Add definition of _WIN32_WINNT as 0x600.
(check_syscall_func, pre_syscall, post_syscall): New.
(gnupg_spawn_process): Remove.
(check_windows_version): New.
(spawn_detached, gnupg_spawn_helper, gnupg_process_spawn): New.
(gnupg_process_get_fds, gnupg_process_get_streams): New.
(process_kill, process_vctl, gnupg_process_ctl): New.
(gnupg_process_wait, gnupg_process_terminate): New.
(gnupg_process_release, gnupg_process_wait_list): New.
* common/exechelp.h: Re-write for new API.
* common/exectool.c (gnupg_exec_tool_stream): Follow the change.
* common/asshelp.c (start_new_service): Likewise.
* agent/genkey.c (do_check_passphrase_pattern): Likewise.
* dirmngr/ldap-wrapper.c (struct wrapper_context_s): Use PROC.
(destroy_wrapper): Follow the change of API.
(read_log_data): Follow the change of API, use printable_pid.
(ldap_reaper_thread, ldap_wrapper_release_context): Likewise.
(ldap_wrapper_connection_cleanup, ldap_wrapper): Likewise.
* g10/photoid.c (run_with_pipe): Follow the change of API.
(show_photo): Likewise.
* g13/be-encfs.c (run_umount_helper): Likewise.
(run_encfs_tool): Likewise.
* g13/g13.c: Add including ./common/exechelp.h.
* g13/mount.c: Likewise.
* g13/runner.c: Follow the change of API.
* g13/runner.h: Follow the change of API.
* scd/app.c (setup_env): New.
(report_change): Follow the change of API.
* tests/gpgscm/ffi.c (proc_object_finalize): New.
(proc_object_to_string): New.
(proc_wrap, proc_unwrap): New.
(do_spawn_process): Remove.
(do_process_spawn): New.
(setup_std_fds): New.
(do_spawn_process_fd): Remove.
(do_process_spawn_fd): New.
(do_wait_process): Remove.
(do_process_wait): New.
(do_wait_processes): Remove.
* tests/gpgscm/t-child.scm: Follow the change of API.
* tests/gpgscm/tests.scm: Likewise.
* tests/openpgp/defs.scm: Likewise.
* tests/tpm2dtests/defs.scm: Likewise.
* tools/gpg-card.c: Likewise.
* tools/gpgconf-comp.c: Likewise.
* tools/gpgconf.c: Likewise.
* tools/gpgtar-create.c: Likewise.
* tools/gpgtar-extract.c: Likewise.
* tools/gpgtar-list.c: Likewise.

--

GnuPG-bug-id: 6275
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2023-05-11 19:18:21 +09:00
parent 1e41878bf2
commit a035938216
No known key found for this signature in database
GPG Key ID: 640114AF89DE6054
25 changed files with 1936 additions and 1621 deletions

View File

@ -99,7 +99,7 @@ do_check_passphrase_pattern (ctrl_t ctrl, const char *pw, unsigned int flags)
const char *pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CHECK_PATTERN);
estream_t stream_to_check_pattern = NULL;
const char *argv[10];
pid_t pid;
gnupg_process_t proc;
int result, i;
const char *pattern;
char *patternfname;
@ -142,11 +142,17 @@ do_check_passphrase_pattern (ctrl_t ctrl, const char *pw, unsigned int flags)
argv[i] = NULL;
log_assert (i < sizeof argv);
if (gnupg_spawn_process (pgmname, argv, NULL, 0,
&stream_to_check_pattern, NULL, NULL, &pid))
if (gnupg_process_spawn (pgmname, argv,
GNUPG_PROCESS_STDIN_PIPE,
NULL, NULL, &proc))
result = 1; /* Execute error - assume password should no be used. */
else
{
int status;
gnupg_process_get_streams (proc, 0, &stream_to_check_pattern,
NULL, NULL);
es_set_binary (stream_to_check_pattern);
if (es_fwrite (pw, strlen (pw), 1, stream_to_check_pattern) != 1)
{
@ -157,11 +163,13 @@ do_check_passphrase_pattern (ctrl_t ctrl, const char *pw, unsigned int flags)
else
es_fflush (stream_to_check_pattern);
es_fclose (stream_to_check_pattern);
if (gnupg_wait_process (pgmname, pid, 1, NULL))
gnupg_process_wait (proc, 1);
gnupg_process_ctl (proc, GNUPG_PROCESS_GET_EXIT_ID, &status);
if (status)
result = 1; /* Helper returned an error - probably a match. */
else
result = 0; /* Success; i.e. no match. */
gnupg_release_process (pid);
gnupg_process_release (proc);
}
xfree (patternfname);

View File

@ -523,16 +523,12 @@ start_new_service (assuan_context_t *r_ctx,
&& assuan_socket_connect (ctx, sockname, 0, connect_flags))
{
#ifdef HAVE_W32_SYSTEM
err = gnupg_spawn_process_detached (program? program : program_name,
argv, NULL);
err = gnupg_process_spawn (program? program : program_name, argv,
GNUPG_PROCESS_DETACHED,
NULL, NULL, NULL);
#else /*!W32*/
pid_t pid;
err = gnupg_spawn_process_fd (program? program : program_name,
argv, -1, -1, -1, &pid);
if (!err)
err = gnupg_wait_process (program? program : program_name,
pid, 1, NULL);
err = gnupg_process_spawn (program? program : program_name, argv,
0, NULL, NULL, NULL);
#endif /*!W32*/
if (err)
log_error ("failed to start %s '%s': %s\n",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -73,140 +73,103 @@ gpg_error_t gnupg_create_pipe (int filedes[2]);
void gnupg_close_pipe (int fd);
#define GNUPG_SPAWN_NONBLOCK 16
#define GNUPG_SPAWN_RUN_ASFW 64
#define GNUPG_SPAWN_DETACHED 128
#define GNUPG_SPAWN_KEEP_STDIN 256
#define GNUPG_SPAWN_KEEP_STDOUT 512
#define GNUPG_SPAWN_KEEP_STDERR 1024
/* The opaque type for a subprocess. */
typedef struct gnupg_process *gnupg_process_t;
#ifdef HAVE_W32_SYSTEM
struct spawn_cb_arg;
#ifdef NEED_STRUCT_SPAWN_CB_ARG
struct spawn_cb_arg {
HANDLE hd[3];
HANDLE *inherit_hds;
BOOL allow_foreground_window;
void *arg;
};
#endif
#else
struct spawn_cb_arg {
int fds[3];
int *except_fds;
void *arg;
};
#endif
/* Fork and exec the program PGMNAME.
#define GNUPG_PROCESS_DETACHED (1 << 1)
If R_INFP is NULL connect stdin of the new process to /dev/null; if
it is not NULL store the address of a pointer to a new estream
there. If R_OUTFP is NULL connect stdout of the new process to
/dev/null; if it is not NULL store the address of a pointer to a
new estream there. If R_ERRFP is NULL connect stderr of the new
process to /dev/null; if it is not NULL store the address of a
pointer to a new estream there. On success the pid of the new
process is stored at PID. On error -1 is stored at PID and if
R_OUTFP or R_ERRFP are not NULL, NULL is stored there.
/* Specify how to keep/connect standard fds. */
#define GNUPG_PROCESS_STDIN_PIPE (1 << 8)
#define GNUPG_PROCESS_STDOUT_PIPE (1 << 9)
#define GNUPG_PROCESS_STDERR_PIPE (1 << 10)
#define GNUPG_PROCESS_STDINOUT_SOCKETPAIR (1 << 11)
#define GNUPG_PROCESS_STDIN_KEEP (1 << 12)
#define GNUPG_PROCESS_STDOUT_KEEP (1 << 13)
#define GNUPG_PROCESS_STDERR_KEEP (1 << 14)
#define GNUPG_PROCESS_STDFDS_SETTING ( GNUPG_PROCESS_STDIN_PIPE \
| GNUPG_PROCESS_STDOUT_PIPE | GNUPG_PROCESS_STDERR_PIPE \
| GNUPG_PROCESS_STDINOUT_SOCKETPAIR | GNUPG_PROCESS_STDIN_KEEP \
| GNUPG_PROCESS_STDOUT_KEEP | GNUPG_PROCESS_STDERR_KEEP)
The arguments for the process are expected in the NULL terminated
array ARGV. The program name itself should not be included there.
If PREEXEC is not NULL, the given function will be called right
before the exec.
#define GNUPG_PROCESS_STREAM_NONBLOCK (1 << 16)
IF EXCEPT is not NULL, it is expected to be an ordered list of file
descriptors, terminated by an entry with the value (-1). These
file descriptors won't be closed before spawning a new program.
/* Spawn helper. */
void gnupg_spawn_helper (struct spawn_cb_arg *sca);
Returns 0 on success or an error code. Calling gnupg_wait_process
and gnupg_release_process is required if the function succeeded.
/* Spawn PGMNAME. */
gpg_err_code_t gnupg_process_spawn (const char *pgmname, const char *argv[],
unsigned int flags,
void (*spawn_cb) (struct spawn_cb_arg *),
void *spawn_cb_arg,
gnupg_process_t *r_process);
FLAGS is a bit vector:
/* Get FDs for subprocess I/O. It is the caller which should care
FDs (closing FDs). */
gpg_err_code_t gnupg_process_get_fds (gnupg_process_t process,
unsigned int flags,
int *r_fd_in, int *r_fd_out,
int *r_fd_err);
GNUPG_SPAWN_NONBLOCK
If set the two output streams are created in non-blocking
mode and the input stream is switched to non-blocking mode.
This is merely a convenience feature because the caller
could do the same with gpgrt_set_nonblock. Does not yet
work for Windows.
/* Get STREAMs for subprocess I/O. It is the caller which should care
STREAMs (closing STREAMs). */
gpg_err_code_t gnupg_process_get_streams (gnupg_process_t process,
unsigned int flags,
gpgrt_stream_t *r_fp_in,
gpgrt_stream_t *r_fp_out,
gpgrt_stream_t *r_fp_err);
GNUPG_SPAWN_DETACHED
If set the process will be started as a background process.
This flag is only useful under W32 (but not W32CE) systems,
so that no new console is created and pops up a console
window when starting the server. Does not work on W32CE.
enum gnupg_process_requests
{
/* Portable requests */
GNUPG_PROCESS_NOP = 0,
GNUPG_PROCESS_GET_PROC_ID = 1,
GNUPG_PROCESS_GET_EXIT_ID = 2,
GNUPG_SPAWN_RUN_ASFW
On W32 (but not on W32CE) run AllowSetForegroundWindow for
the child. Note that due to unknown problems this actually
allows SetForegroundWindow for all children of this process.
/* POSIX only */
GNUPG_PROCESS_GET_PID = 16,
GNUPG_PROCESS_GET_WSTATUS = 17,
GNUPG_PROCESS_KILL = 18,
GNUPG_SPAWN_KEEP_STDIN
GNUPG_SPAWN_KEEP_STDOUT
GNUPG_SPAWN_KEEP_STDERR
Do not assign /dev/null to a non-required standard file
descriptor.
/* Windows only */
GNUPG_PROCESS_GET_P_HANDLE = 32,
GNUPG_PROCESS_GET_HANDLES = 33,
GNUPG_PROCESS_GET_EXIT_CODE = 34,
GNUPG_PROCESS_KILL_WITH_EC = 35
};
*/
gpg_error_t
gnupg_spawn_process (const char *pgmname, const char *argv[],
int *execpt, unsigned int flags,
estream_t *r_infp,
estream_t *r_outfp,
estream_t *r_errfp,
pid_t *pid);
/* Control of a process. */
gpg_err_code_t gnupg_process_ctl (gnupg_process_t process,
unsigned int request, ...);
/* Wait for a single PROCESS. */
gpg_err_code_t gnupg_process_wait (gnupg_process_t process, int hang);
/* Simplified version of gnupg_spawn_process. This function forks and
then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout
and ERRFD to stderr (any of them may be -1 to connect them to
/dev/null). The arguments for the process are expected in the NULL
terminated array ARGV. The program name itself should not be
included there. Calling gnupg_wait_process and
gnupg_release_process is required. Returns 0 on success or an
error code. */
gpg_error_t gnupg_spawn_process_fd (const char *pgmname,
const char *argv[],
int infd, int outfd, int errfd,
pid_t *pid);
/* Terminate a PROCESS. */
gpg_err_code_t gnupg_process_terminate (gnupg_process_t process);
/* Release PROCESS resources. */
void gnupg_process_release (gnupg_process_t process);
/* If HANG is true, waits for the process identified by PID to exit;
if HANG is false, checks whether the process has terminated.
PGMNAME should be the same as supplied to the spawn function and is
only used for diagnostics. Return values:
0
The process exited successful. 0 is stored at R_EXITCODE.
GPG_ERR_GENERAL
The process exited without success. The exit code of process
is then stored at R_EXITCODE. An exit code of -1 indicates
that the process terminated abnormally (e.g. due to a signal).
GPG_ERR_TIMEOUT
The process is still running (returned only if HANG is false).
GPG_ERR_INV_VALUE
An invalid PID has been specified.
Other error codes may be returned as well. Unless otherwise noted,
-1 will be stored at R_EXITCODE. R_EXITCODE may be passed as NULL
if the exit code is not required (in that case an error message will
be printed). Note that under Windows PID is not the process id but
the handle of the process. */
gpg_error_t gnupg_wait_process (const char *pgmname, pid_t pid, int hang,
int *r_exitcode);
/* Like gnupg_wait_process, but for COUNT processes. */
gpg_error_t gnupg_wait_processes (const char **pgmnames, pid_t *pids,
size_t count, int hang, int *r_exitcodes);
/* Kill a process; that is send an appropriate signal to the process.
gnupg_wait_process must be called to actually remove the process
from the system. An invalid PID is ignored. */
void gnupg_kill_process (pid_t pid);
/* Release the process identified by PID. This function is actually
only required for Windows but it does not harm to always call it.
It is a nop if PID is invalid. */
void gnupg_release_process (pid_t pid);
/* Spawn a new process and immediately detach from it. The name of
the program to exec is PGMNAME and its arguments are in ARGV (the
programname is automatically passed as first argument).
Environment strings in ENVP are set. An error is returned if
pgmname is not executable; to make this work it is necessary to
provide an absolute file name. */
gpg_error_t gnupg_spawn_process_detached (const char *pgmname,
const char *argv[],
const char *envp[] );
/* Wait for a multiple processes. */
gpg_err_code_t gnupg_process_wait_list (gnupg_process_t *process_list,
int count, int hang);
#endif /*GNUPG_COMMON_EXECHELP_H*/

View File

@ -38,10 +38,14 @@
#include <gpg-error.h>
#include <assuan.h>
#include "i18n.h"
#include "logging.h"
#include "membuf.h"
#include "mischelp.h"
#ifdef HAVE_W32_SYSTEM
#define NEED_STRUCT_SPAWN_CB_ARG 1
#endif
#include "exechelp.h"
#include "sysutils.h"
#include "util.h"
@ -301,7 +305,6 @@ copy_buffer_flush (struct copy_buffer *c, estream_t sink)
}
/* Run the program PGMNAME with the command line arguments given in
* the NULL terminates array ARGV. If INPUT is not NULL it will be
* fed to stdin of the process. stderr is logged using log_info and
@ -321,7 +324,7 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
void *status_cb_value)
{
gpg_error_t err;
pid_t pid = (pid_t) -1;
gnupg_process_t proc = NULL;
estream_t infp = NULL;
estream_t extrafp = NULL;
estream_t outfp = NULL, errfp = NULL;
@ -335,7 +338,6 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
read_and_log_buffer_t fderrstate;
struct copy_buffer *cpbuf_in = NULL, *cpbuf_out = NULL, *cpbuf_extra = NULL;
int quiet = 0;
int dummy_exitcode;
memset (fds, 0, sizeof fds);
memset (&fderrstate, 0, sizeof fderrstate);
@ -411,10 +413,15 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
else
exceptclose[0] = -1;
err = gnupg_spawn_process (pgmname, argv,
exceptclose, GNUPG_SPAWN_NONBLOCK,
input? &infp : NULL,
&outfp, &errfp, &pid);
err = gnupg_process_spawn (pgmname, argv,
((input
? GNUPG_PROCESS_STDIN_PIPE
: 0)
| GNUPG_PROCESS_STDOUT_PIPE
| GNUPG_PROCESS_STDERR_PIPE),
gnupg_spawn_helper, exceptclose, &proc);
gnupg_process_get_streams (proc, GNUPG_PROCESS_STREAM_NONBLOCK,
input? &infp : NULL, &outfp, &errfp);
if (extrapipe[0] != -1)
close (extrapipe[0]);
if (argsave)
@ -546,20 +553,25 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
es_fclose (outfp); outfp = NULL;
es_fclose (errfp); errfp = NULL;
err = gnupg_wait_process (pgmname, pid, 1, quiet? &dummy_exitcode : NULL);
pid = (pid_t)(-1);
err = gnupg_process_wait (proc, 1);
if (!err)
{ /* To be compatible to old wait_process. */
int status;
gnupg_process_ctl (proc, GNUPG_PROCESS_GET_EXIT_ID, &status);
if (status)
err = gpg_error (GPG_ERR_GENERAL);
}
leave:
if (err && pid != (pid_t) -1)
gnupg_kill_process (pid);
if (err && proc)
gnupg_process_terminate (proc);
es_fclose (infp);
es_fclose (extrafp);
es_fclose (outfp);
es_fclose (errfp);
if (pid != (pid_t)(-1))
gnupg_wait_process (pgmname, pid, 1, quiet? &dummy_exitcode : NULL);
gnupg_release_process (pid);
gnupg_process_release (proc);
copy_buffer_shred (cpbuf_in);
xfree (cpbuf_in);

View File

@ -87,7 +87,7 @@ struct wrapper_context_s
{
struct wrapper_context_s *next;
pid_t pid; /* The pid of the wrapper process. */
gnupg_process_t proc;/* The wrapper process. */
int printable_pid; /* Helper to print diagnostics after the process has
* been cleaned up. */
estream_t fp; /* Connected with stdout of the ldap wrapper. */
@ -170,10 +170,10 @@ read_buffer (ksba_reader_t reader, unsigned char *buffer, size_t count)
static void
destroy_wrapper (struct wrapper_context_s *ctx)
{
if (ctx->pid != (pid_t)(-1))
if (ctx->proc)
{
gnupg_kill_process (ctx->pid);
gnupg_release_process (ctx->pid);
gnupg_process_terminate (ctx->proc);
gnupg_process_release (ctx->proc);
}
ksba_reader_release (ctx->reader);
SAFE_CLOSE (ctx->fp);
@ -260,7 +260,7 @@ read_log_data (struct wrapper_context_s *ctx)
if (gpg_err_code (err) == GPG_ERR_EAGAIN)
return 0;
log_error (_("error reading log from ldap wrapper %d: %s\n"),
(int)ctx->pid, gpg_strerror (err));
ctx->printable_pid, gpg_strerror (err));
}
print_log_line (ctx, NULL); /* Flush. */
SAFE_CLOSE (ctx->log_fp);
@ -438,50 +438,44 @@ ldap_reaper_thread (void *dummy)
}
/* Check whether the process is still running. */
if (ctx->pid != (pid_t)(-1))
if (ctx->proc)
{
int status;
err = gnupg_wait_process ("[dirmngr_ldap]", ctx->pid, 0,
&status);
err = gnupg_process_wait (ctx->proc, 0);
if (!err)
{
int status;
gnupg_process_ctl (ctx->proc, GNUPG_PROCESS_GET_EXIT_ID,
&status);
if (DBG_EXTPROG)
log_info (_("ldap wrapper %d ready"), (int)ctx->pid);
log_info (_("ldap wrapper %d ready"), ctx->printable_pid);
ctx->ready = 1;
gnupg_release_process (ctx->pid);
ctx->pid = (pid_t)(-1);
gnupg_process_release (ctx->proc);
ctx->proc = NULL;
any_action = 1;
}
else if (gpg_err_code (err) == GPG_ERR_GENERAL)
{
if (status == 10)
log_info (_("ldap wrapper %d ready: timeout\n"),
(int)ctx->pid);
ctx->printable_pid);
else
log_info (_("ldap wrapper %d ready: exitcode=%d\n"),
(int)ctx->pid, status);
ctx->ready = 1;
gnupg_release_process (ctx->pid);
ctx->pid = (pid_t)(-1);
any_action = 1;
ctx->printable_pid, status);
}
else if (gpg_err_code (err) != GPG_ERR_TIMEOUT)
{
log_error (_("waiting for ldap wrapper %d failed: %s\n"),
(int)ctx->pid, gpg_strerror (err));
ctx->printable_pid, gpg_strerror (err));
any_action = 1;
}
}
/* Check whether we should terminate the process. */
if (ctx->pid != (pid_t)(-1)
&& ctx->stamp != (time_t)(-1) && ctx->stamp < exptime)
if (ctx->proc && ctx->stamp != (time_t)(-1) && ctx->stamp < exptime)
{
gnupg_kill_process (ctx->pid);
gnupg_process_terminate (ctx->proc);
ctx->stamp = (time_t)(-1);
log_info (_("ldap wrapper %d stalled - killing\n"),
(int)ctx->pid);
ctx->printable_pid);
/* We need to close the log stream because the cleanup
* loop waits for it. */
SAFE_CLOSE (ctx->log_fp);
@ -496,10 +490,10 @@ ldap_reaper_thread (void *dummy)
{
log_debug ("ldap worker states:\n");
for (ctx = reaper_list; ctx; ctx = ctx->next)
log_debug (" c=%p pid=%d/%d rdr=%p logfp=%p"
log_debug (" c=%p pid=%d rdr=%p logfp=%p"
" ctrl=%p/%d la=%lu rdy=%d\n",
ctx,
(int)ctx->pid, (int)ctx->printable_pid,
ctx->printable_pid,
ctx->reader, ctx->log_fp,
ctx->ctrl, ctx->ctrl? ctx->ctrl->refcount:0,
(unsigned long)ctx->stamp, ctx->ready);
@ -602,9 +596,9 @@ ldap_wrapper_release_context (ksba_reader_t reader)
if (ctx->reader == reader)
{
if (DBG_EXTPROG)
log_debug ("releasing ldap worker c=%p pid=%d/%d rdr=%p"
log_debug ("releasing ldap worker c=%p pid=%d rdr=%p"
" ctrl=%p/%d\n", ctx,
(int)ctx->pid, (int)ctx->printable_pid,
ctx->printable_pid,
ctx->reader,
ctx->ctrl, ctx->ctrl? ctx->ctrl->refcount:0);
@ -639,8 +633,8 @@ ldap_wrapper_connection_cleanup (ctrl_t ctrl)
{
ctx->ctrl->refcount--;
ctx->ctrl = NULL;
if (ctx->pid != (pid_t)(-1))
gnupg_kill_process (ctx->pid);
if (ctx->proc)
gnupg_process_terminate (ctx->proc);
if (ctx->fp_err)
log_info ("%s: reading from ldap wrapper %d failed: %s\n",
__func__, ctx->printable_pid, gpg_strerror (ctx->fp_err));
@ -798,7 +792,7 @@ gpg_error_t
ldap_wrapper (ctrl_t ctrl, ksba_reader_t *reader, const char *argv[])
{
gpg_error_t err;
pid_t pid;
gnupg_process_t process;
struct wrapper_context_s *ctx;
int i;
int j;
@ -854,19 +848,22 @@ ldap_wrapper (ctrl_t ctrl, ksba_reader_t *reader, const char *argv[])
return err;
}
err = gnupg_spawn_process (pgmname, arg_list,
NULL, GNUPG_SPAWN_NONBLOCK,
NULL, &outfp, &errfp, &pid);
err = gnupg_process_spawn (pgmname, arg_list,
(GNUPG_PROCESS_STDOUT_PIPE
| GNUPG_PROCESS_STDERR_PIPE),
NULL, NULL, &process);
if (err)
{
xfree (arg_list);
xfree (arg_list);
xfree (ctx);
log_error ("error running '%s': %s\n", pgmname, gpg_strerror (err));
return err;
}
gnupg_process_get_streams (process, GNUPG_PROCESS_STREAM_NONBLOCK,
NULL, &outfp, &errfp);
gnupg_process_ctl (process, GNUPG_PROCESS_GET_PROC_ID, &ctx->printable_pid);
ctx->pid = pid;
ctx->printable_pid = (int) pid;
ctx->proc = process;
ctx->fp = outfp;
ctx->log_fp = errfp;
ctx->ctrl = ctrl;
@ -902,7 +899,7 @@ ldap_wrapper (ctrl_t ctrl, ksba_reader_t *reader, const char *argv[])
if (DBG_EXTPROG)
{
log_debug ("ldap wrapper %d started (%p, %s)",
(int)ctx->pid, ctx->reader, pgmname);
ctx->printable_pid, ctx->reader, pgmname);
for (i=0; arg_list[i]; i++)
log_printf (" [%s]", arg_list[i]);
log_printf ("\n");

View File

@ -594,34 +594,35 @@ run_with_pipe (struct spawn_info *info, const void *image, u32 len)
" external programs\n"));
return;
#else /* !EXEC_TEMPFILE_ONLY */
int to[2];
pid_t pid;
gpg_error_t err;
const char *argv[4];
err = gnupg_create_pipe (to);
if (err)
return;
gnupg_process_t proc;
fill_command_argv (argv, info->command);
err = gnupg_spawn_process_fd (argv[0], argv+1, to[0], -1, -1, &pid);
close (to[0]);
err = gnupg_process_spawn (argv[0], argv+1, GNUPG_PROCESS_STDIN_PIPE,
NULL, NULL, &proc);
if (err)
{
log_error (_("unable to execute shell '%s': %s\n"),
argv[0], gpg_strerror (err));
close (to[1]);
}
log_error (_("unable to execute shell '%s': %s\n"),
argv[0], gpg_strerror (err));
else
{
write (to[1], image, len);
close (to[1]);
int fd_in;
err = gnupg_wait_process (argv[0], pid, 1, NULL);
err = gnupg_process_get_fds (proc, 0, &fd_in, NULL, NULL);
if (err)
log_error ("unable to get pipe connection '%s': %s\n",
argv[2], gpg_strerror (err));
else
{
write (fd_in, image, len);
close (fd_in);
}
err = gnupg_process_wait (proc, 1);
if (err)
log_error (_("unnatural exit of external program\n"));
gnupg_process_release (proc);
}
#endif /* !EXEC_TEMPFILE_ONLY */
}
@ -689,14 +690,11 @@ show_photo (const char *command, const char *name, const void *image, u32 len)
log_error (_("system error while calling external program: %s\n"),
strerror (errno));
#else
pid_t pid;
gpg_error_t err;
const char *argv[4];
fill_command_argv (argv, spawn->command);
err = gnupg_spawn_process_fd (argv[0], argv+1, -1, -1, -1, &pid);
if (!err)
err = gnupg_wait_process (argv[0], pid, 1, NULL);
err = gnupg_process_spawn (argv[0], argv+1, 0, NULL, NULL, NULL);
if (err)
log_error (_("unnatural exit of external program\n"));
#endif

View File

@ -28,10 +28,10 @@
#include "g13.h"
#include "../common/i18n.h"
#include "keyblob.h"
#include "be-encfs.h"
#include "runner.h"
#include "../common/sysutils.h"
#include "../common/exechelp.h"
#include "runner.h"
#include "be-encfs.h"
/* Command values used to run the encfs tool. */
@ -81,7 +81,9 @@ run_umount_helper (const char *mountpoint)
args[1] = mountpoint;
args[2] = NULL;
err = gnupg_spawn_process_detached (pgmname, args, NULL);
err = gnupg_process_spawn (pgmname, args,
GNUPG_PROCESS_DETACHED,
NULL, NULL, NULL);
if (err)
log_error ("failed to run '%s': %s\n",
pgmname, gpg_strerror (err));
@ -218,12 +220,11 @@ run_encfs_tool (ctrl_t ctrl, enum encfs_cmds cmd,
gpg_error_t err;
encfs_parm_t parm;
runner_t runner = NULL;
int outbound[2] = { -1, -1 };
int inbound[2] = { -1, -1 };
const char *pgmname;
const char *argv[10];
pid_t pid = (pid_t)(-1);
int idx;
gnupg_process_t proc;
int inbound, outbound;
(void)ctrl;
@ -246,15 +247,6 @@ run_encfs_tool (ctrl_t ctrl, enum encfs_cmds cmd,
if (err)
goto leave;
err = gnupg_create_inbound_pipe (inbound, NULL, 0);
if (!err)
err = gnupg_create_outbound_pipe (outbound, NULL, 0);
if (err)
{
log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
goto leave;
}
pgmname = ENCFS;
idx = 0;
argv[idx++] = "-f";
@ -267,47 +259,42 @@ run_encfs_tool (ctrl_t ctrl, enum encfs_cmds cmd,
argv[idx++] = NULL;
assert (idx <= DIM (argv));
err = gnupg_spawn_process_fd (pgmname, argv,
outbound[0], -1, inbound[1], &pid);
err = gnupg_process_spawn (pgmname, argv,
(GNUPG_PROCESS_STDIN_PIPE
| GNUPG_PROCESS_STDERR_PIPE),
NULL, NULL, &proc);
if (err)
{
log_error ("error spawning '%s': %s\n", pgmname, gpg_strerror (err));
goto leave;
}
close (outbound[0]); outbound[0] = -1;
close ( inbound[1]); inbound[1] = -1;
runner_set_fds (runner, inbound[0], outbound[1]);
inbound[0] = -1; /* Now owned by RUNNER. */
outbound[1] = -1; /* Now owned by RUNNER. */
err = gnupg_process_get_fds (proc, 0, &outbound, NULL, &inbound);
if (err)
{
log_error ("error get fds '%s': %s\n", pgmname, gpg_strerror (err));
gnupg_process_release (proc);
goto leave;
}
runner_set_fds (runner, inbound, outbound);
runner_set_handler (runner, encfs_handler, encfs_handler_cleanup, parm);
parm = NULL; /* Now owned by RUNNER. */
runner_set_pid (runner, pid);
pid = (pid_t)(-1); /* The process is now owned by RUNNER. */
runner_set_proc (runner, proc);
err = runner_spawn (runner);
if (err)
goto leave;
{
gnupg_process_release (proc);
goto leave;
}
*r_id = runner_get_rid (runner);
log_info ("running '%s' in the background\n", pgmname);
leave:
if (inbound[0] != -1)
close (inbound[0]);
if (inbound[1] != -1)
close (inbound[1]);
if (outbound[0] != -1)
close (outbound[0]);
if (outbound[1] != -1)
close (outbound[1]);
if (pid != (pid_t)(-1))
{
gnupg_wait_process (pgmname, pid, 1, NULL);
gnupg_release_process (pid);
}
runner_release (runner);
encfs_handler_cleanup (parm);
return err;

View File

@ -40,6 +40,7 @@
#include "../common/gc-opt-flags.h"
#include "../common/asshelp.h"
#include "../common/init.h"
#include "../common/exechelp.h"
#include "keyblob.h"
#include "server.h"
#include "runner.h"

View File

@ -34,10 +34,11 @@
#include "backend.h"
#include "g13tuple.h"
#include "mountinfo.h"
#include "runner.h"
#include "../common/host2net.h"
#include "server.h" /*(g13_keyblob_decrypt)*/
#include "../common/sysutils.h"
#include "../common/exechelp.h"
#include "runner.h"
#include "call-syshelp.h"

View File

@ -29,8 +29,8 @@
#include "g13.h"
#include "../common/i18n.h"
#include "keyblob.h"
#include "runner.h"
#include "../common/exechelp.h"
#include "runner.h"
#include "mountinfo.h"
/* The runner object. */
@ -55,7 +55,7 @@ struct runner_s
2 = Thread is running and someone is holding a reference. */
int refcount;
pid_t pid; /* PID of the backend's process (the engine). */
gnupg_process_t proc; /* Process of the backend's process (the engine). */
int in_fd; /* File descriptors to read from the engine. */
int out_fd; /* File descriptors to write to the engine. */
engine_handler_fnc_t handler; /* The handler functions. */
@ -157,16 +157,16 @@ runner_release (runner_t runner)
if (runner->handler_cleanup)
runner->handler_cleanup (runner->handler_data);
if (runner->pid != (pid_t)(-1))
if (runner->proc)
{
/* The process has not been cleaned up - do it now. */
gnupg_kill_process (runner->pid);
gnupg_process_terminate (runner->proc);
/* (Actually we should use the program name and not the
arbitrary NAME of the runner object. However it does not
matter because that information is only used for
diagnostics.) */
gnupg_wait_process (runner->name, runner->pid, 1, NULL);
gnupg_release_process (runner->pid);
gnupg_process_wait (runner->proc, 1);
gnupg_process_release (runner->proc);
}
xfree (runner->name);
@ -212,7 +212,7 @@ runner_new (runner_t *r_runner, const char *name)
return gpg_error_from_syserror ();
}
runner->refcount = 1;
runner->pid = (pid_t)(-1);
runner->proc = NULL;
runner->in_fd = -1;
runner->out_fd = -1;
@ -266,15 +266,15 @@ runner_set_fds (runner_t runner, int in_fd, int out_fd)
}
/* Set the PID of the backend engine. After this call the engine is
/* Set the PROC of the backend engine. After this call the engine is
owned by the runner object. */
void
runner_set_pid (runner_t runner, pid_t pid)
runner_set_proc (runner_t runner, gnupg_process_t proc)
{
if (check_already_spawned (runner, "runner_set_fds"))
if (check_already_spawned (runner, "runner_set_proc"))
return;
runner->pid = pid;
runner->proc = proc;
}
@ -366,15 +366,17 @@ runner_thread (void *arg)
}
/* Now wait for the process to finish. */
if (!err && runner->pid != (pid_t)(-1))
if (!err && runner->proc)
{
int exitcode;
log_debug ("runner thread waiting ...\n");
err = gnupg_wait_process (runner->name, runner->pid, 1, &exitcode);
gnupg_release_process (runner->pid);
runner->pid = (pid_t)(-1);
if (err)
err = gnupg_process_wait (runner->proc, 1);
if (!err)
gnupg_process_ctl (runner->proc, GNUPG_PROCESS_GET_EXIT_ID, &exitcode);
gnupg_process_release (runner->proc);
runner->proc = NULL;
if (exitcode)
log_error ("running '%s' failed (exitcode=%d): %s\n",
runner->name, exitcode, gpg_strerror (err));
log_debug ("runner thread waiting finished\n");
@ -473,7 +475,7 @@ runner_cancel (runner_t runner)
need to change the thread to wait on an event. */
runner->cancel_flag = 1;
/* For now we use the brutal way and kill the process. */
gnupg_kill_process (runner->pid);
gnupg_process_terminate (runner->proc);
}
}

View File

@ -49,7 +49,7 @@ runner_t runner_find_by_rid (unsigned int rid);
/* Functions to set properties of the runner. */
void runner_set_fds (runner_t runner, int in_fd, int out_fd);
void runner_set_pid (runner_t runner, pid_t pid);
void runner_set_proc (runner_t runner, gnupg_process_t proc);
/* Register the handler functions with a runner. */
void runner_set_handler (runner_t runner,

View File

@ -2333,6 +2333,18 @@ app_check_pin (card_t card, ctrl_t ctrl, const char *keyidstr,
}
static void
setup_env (struct spawn_cb_arg *sca)
{
#ifdef HAVE_W32_SYSTEM
(void)sca; /* Not supported on Windows. */
#else
char *v = sca->arg;
putenv (v);
#endif
}
static void
report_change (int slot, int old_status, int cur_status)
{
@ -2360,12 +2372,9 @@ report_change (int slot, int old_status, int cur_status)
else
{
gpg_error_t err;
const char *args[9], *envs[2];
const char *args[9];
char numbuf1[30], numbuf2[30], numbuf3[30];
envs[0] = envstr;
envs[1] = NULL;
sprintf (numbuf1, "%d", slot);
sprintf (numbuf2, "0x%04X", old_status);
sprintf (numbuf3, "0x%04X", cur_status);
@ -2382,7 +2391,9 @@ report_change (int slot, int old_status, int cur_status)
args[8] = NULL;
fname = make_filename (gnupg_homedir (), "scd-event", NULL);
err = gnupg_spawn_process_detached (fname, args, envs);
err = gnupg_process_spawn (fname, args,
GNUPG_PROCESS_DETACHED,
setup_env, envstr, NULL);
if (err && gpg_err_code (err) != GPG_ERR_ENOENT)
log_error ("failed to run event handler '%s': %s\n",
fname, gpg_strerror (err));

View File

@ -42,6 +42,9 @@
#endif
#include "../../common/util.h"
#ifdef HAVE_W32_SYSTEM
#define NEED_STRUCT_SPAWN_CB_ARG
#endif
#include "../../common/exechelp.h"
#include "../../common/sysutils.h"
@ -753,25 +756,86 @@ do_es_write (scheme *sc, pointer args)
}
/* Process handling. */
struct proc_object_box
{
gnupg_process_t proc;
};
static void
proc_object_finalize (scheme *sc, void *data)
{
struct proc_object_box *box = data;
(void) sc;
if (!box->proc)
gnupg_process_release (box->proc);
xfree (box);
}
static void
proc_object_to_string (scheme *sc, char *out, size_t size, void *data)
{
struct proc_object_box *box = data;
(void) sc;
snprintf (out, size, "#proc %p", box->proc);
}
static struct foreign_object_vtable proc_object_vtable =
{
proc_object_finalize,
proc_object_to_string,
};
static pointer
do_spawn_process (scheme *sc, pointer args)
proc_wrap (scheme *sc, gnupg_process_t proc)
{
struct proc_object_box *box = xmalloc (sizeof *box);
if (box == NULL)
return sc->NIL;
box->proc = proc;
return sc->vptr->mk_foreign_object (sc, &proc_object_vtable, box);
}
static struct proc_object_box *
proc_unwrap (scheme *sc, pointer object)
{
(void) sc;
if (! is_foreign_object (object))
return NULL;
if (sc->vptr->get_foreign_object_vtable (object) != &proc_object_vtable)
return NULL;
return sc->vptr->get_foreign_object_data (object);
}
#define CONVERSION_proc(SC, X) proc_unwrap (SC, X)
#define IS_A_proc(SC, X) proc_unwrap (SC, X)
static pointer
do_process_spawn (scheme *sc, pointer args)
{
FFI_PROLOG ();
pointer arguments;
char **argv;
size_t len;
unsigned int flags;
gnupg_process_t proc = NULL;
estream_t infp;
estream_t outfp;
estream_t errfp;
pid_t pid;
FFI_ARG_OR_RETURN (sc, pointer, arguments, list, args);
FFI_ARG_OR_RETURN (sc, unsigned int, flags, number, args);
flags |= (GNUPG_PROCESS_STDIN_PIPE
| GNUPG_PROCESS_STDOUT_PIPE
| GNUPG_PROCESS_STDERR_PIPE);
FFI_ARGS_DONE_OR_RETURN (sc, args);
err = ffi_list2argv (sc, arguments, &argv, &len);
@ -791,38 +855,55 @@ do_spawn_process (scheme *sc, pointer args)
fprintf (stderr, "\n");
}
err = gnupg_spawn_process (argv[0], (const char **) &argv[1],
NULL,
flags,
&infp, &outfp, &errfp, &pid);
err = gnupg_process_spawn (argv[0], (const char **) &argv[1],
flags, NULL, NULL, &proc);
err = gnupg_process_get_streams (proc, 0, &infp, &outfp, &errfp);
xfree (argv);
#define IMC(A, B) \
_cons (sc, sc->vptr->mk_integer (sc, (unsigned long) (A)), (B), 1)
#define IMP(A, B) \
_cons (sc, proc_wrap (sc, (A)), (B), 1)
#define IMS(A, B) \
_cons (sc, es_wrap (sc, (A)), (B), 1)
FFI_RETURN_POINTER (sc, IMS (infp,
IMS (outfp,
IMS (errfp,
IMC (pid, sc->NIL)))));
IMP (proc, sc->NIL)))));
#undef IMS
#undef IMC
}
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
do_spawn_process_fd (scheme *sc, pointer args)
do_process_spawn_fd (scheme *sc, pointer args)
{
FFI_PROLOG ();
pointer arguments;
char **argv;
size_t len;
int infd, outfd, errfd;
pid_t pid;
int std_fds[3];
gnupg_process_t proc = NULL;
FFI_ARG_OR_RETURN (sc, pointer, arguments, list, args);
FFI_ARG_OR_RETURN (sc, int, infd, number, args);
FFI_ARG_OR_RETURN (sc, int, outfd, number, args);
FFI_ARG_OR_RETURN (sc, int, errfd, number, args);
FFI_ARG_OR_RETURN (sc, int, std_fds[0], number, args);
FFI_ARG_OR_RETURN (sc, int, std_fds[1], number, args);
FFI_ARG_OR_RETURN (sc, int, std_fds[2], number, args);
FFI_ARGS_DONE_OR_RETURN (sc, args);
err = ffi_list2argv (sc, arguments, &argv, &len);
@ -839,107 +920,35 @@ do_spawn_process_fd (scheme *sc, pointer args)
fprintf (stderr, "Executing:");
for (p = argv; *p; p++)
fprintf (stderr, " '%s'", *p);
fprintf (stderr, "\n");
fprintf (stderr, " (%d %d %d)\n", std_fds[0], std_fds[1], std_fds[2]);
}
err = gnupg_spawn_process_fd (argv[0], (const char **) &argv[1],
infd, outfd, errfd, &pid);
err = gnupg_process_spawn (argv[0], (const char **) &argv[1],
0, setup_std_fds, std_fds, &proc);
xfree (argv);
FFI_RETURN_INT (sc, pid);
FFI_RETURN_POINTER (sc, proc_wrap (sc, proc));
}
static pointer
do_wait_process (scheme *sc, pointer args)
do_process_wait (scheme *sc, pointer args)
{
FFI_PROLOG ();
const char *name;
pid_t pid;
struct proc_object_box *box;
int hang;
int retcode = -1;
int retcode;
FFI_ARG_OR_RETURN (sc, const char *, name, string, args);
FFI_ARG_OR_RETURN (sc, pid_t, pid, number, args);
FFI_ARG_OR_RETURN (sc, struct proc_object_box *, box, proc, args);
FFI_ARG_OR_RETURN (sc, int, hang, bool, args);
FFI_ARGS_DONE_OR_RETURN (sc, args);
err = gnupg_wait_process (name, pid, hang, &retcode);
if (err == GPG_ERR_GENERAL)
err = 0; /* Let the return code speak for itself. */
err = gnupg_process_wait (box->proc, hang);
if (!err)
err = gnupg_process_ctl (box->proc, GNUPG_PROCESS_GET_EXIT_ID, &retcode);
if (err == GPG_ERR_TIMEOUT)
err = 0;
FFI_RETURN_INT (sc, retcode);
}
static pointer
do_wait_processes (scheme *sc, pointer args)
{
FFI_PROLOG ();
pointer list_names;
char **names;
pointer list_pids;
size_t i, count;
pid_t *pids;
int hang;
int *retcodes;
pointer retcodes_list = sc->NIL;
FFI_ARG_OR_RETURN (sc, pointer, list_names, list, args);
FFI_ARG_OR_RETURN (sc, pointer, list_pids, list, args);
FFI_ARG_OR_RETURN (sc, int, hang, bool, args);
FFI_ARGS_DONE_OR_RETURN (sc, args);
if (sc->vptr->list_length (sc, list_names)
!= sc->vptr->list_length (sc, list_pids))
return
sc->vptr->mk_string (sc, "length of first two arguments must match");
err = ffi_list2argv (sc, list_names, &names, &count);
if (err == gpg_error (GPG_ERR_INV_VALUE))
return ffi_sprintf (sc, "%lu%s element of first argument is "
"neither string nor symbol",
(unsigned long) count,
ordinal_suffix ((int) count));
if (err)
FFI_RETURN_ERR (sc, err);
err = ffi_list2intv (sc, list_pids, (int **) &pids, &count);
if (err == gpg_error (GPG_ERR_INV_VALUE))
return ffi_sprintf (sc, "%lu%s element of second argument is "
"not a number",
(unsigned long) count,
ordinal_suffix ((int) count));
if (err)
FFI_RETURN_ERR (sc, err);
retcodes = xtrycalloc (sizeof *retcodes, count);
if (retcodes == NULL)
{
xfree (names);
xfree (pids);
FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
}
err = gnupg_wait_processes ((const char **) names, pids, count, hang,
retcodes);
if (err == GPG_ERR_GENERAL)
err = 0; /* Let the return codes speak. */
if (err == GPG_ERR_TIMEOUT)
err = 0; /* We may have got some results. */
for (i = 0; i < count; i++)
retcodes_list =
(sc->vptr->cons) (sc,
sc->vptr->mk_integer (sc,
(long) retcodes[count-1-i]),
retcodes_list);
xfree (names);
xfree (pids);
xfree (retcodes);
FFI_RETURN_POINTER (sc, retcodes_list);
}
static pointer
do_pipe (scheme *sc, pointer args)
{
@ -1398,13 +1407,12 @@ ffi_init (scheme *sc, const char *argv0, const char *scriptname,
ffi_define_function (sc, make_random_string);
/* Process management. */
ffi_define_function (sc, spawn_process);
ffi_define_function (sc, spawn_process_fd);
ffi_define_function (sc, wait_process);
ffi_define_function (sc, wait_processes);
ffi_define_function (sc, pipe);
ffi_define_function (sc, inbound_pipe);
ffi_define_function (sc, outbound_pipe);
ffi_define_function (sc, process_spawn);
ffi_define_function (sc, process_spawn_fd);
ffi_define_function (sc, process_wait);
/* estream functions. */
ffi_define_function_name (sc, "es-fclose", es_fclose);

View File

@ -69,37 +69,36 @@
(assert (string=? "" (:stderr r))))
(define (spawn what)
(spawn-process-fd what CLOSED_FD STDOUT_FILENO STDERR_FILENO))
(process-spawn-fd what CLOSED_FD STDOUT_FILENO STDERR_FILENO))
(let ((pid0 (spawn `(,(qualify "t-child") "return0")))
(pid1 (spawn `(,(qualify "t-child") "return0"))))
(assert (equal? '(0 0)
(wait-processes '("child0" "child1") (list pid0 pid1) #t))))
(let ((proc0 (spawn `(,(qualify "t-child") "return0")))
(proc1 (spawn `(,(qualify "t-child") "return0"))))
(assert (= (process-wait proc0 #t) 0))
(assert (= (process-wait proc1 #t) 0)))
(let ((pid0 (spawn `(,(qualify "t-child") "return1")))
(pid1 (spawn `(,(qualify "t-child") "return0"))))
(assert (equal? '(1 0)
(wait-processes '("child0" "child1") (list pid0 pid1) #t))))
(let ((proc0 (spawn `(,(qualify "t-child") "return1")))
(proc1 (spawn `(,(qualify "t-child") "return0"))))
(assert (= (process-wait proc0 #t) 1))
(assert (= (process-wait proc1 #t) 0)))
(let ((pid0 (spawn `(,(qualify "t-child") "return0")))
(pid1 (spawn `(,(qualify "t-child") "return77")))
(pid2 (spawn `(,(qualify "t-child") "return1"))))
(assert (equal? '(0 77 1)
(wait-processes '("child0" "child1" "child2")
(list pid0 pid1 pid2) #t))))
(let ((proc0 (spawn `(,(qualify "t-child") "return0")))
(proc1 (spawn `(,(qualify "t-child") "return77")))
(proc2 (spawn `(,(qualify "t-child") "return1"))))
(assert (= (process-wait proc0 #t) 0))
(assert (= (process-wait proc1 #t) 77))
(assert (= (process-wait proc2 #t) 1)))
(let* ((p (pipe))
(pid0 (spawn-process-fd
(proc0 (process-spawn-fd
`(,(qualify "t-child") "hello_stdout")
CLOSED_FD (:write-end p) STDERR_FILENO))
(_ (close (:write-end p)))
(pid1 (spawn-process-fd
(proc1 (process-spawn-fd
`(,(qualify "t-child") "cat")
(:read-end p) STDOUT_FILENO STDERR_FILENO)))
(close (:read-end p))
(assert
(equal? '(0 0)
(wait-processes '("child0" "child1") (list pid0 pid1) #t))))
(assert (= (process-wait proc0 #t) 0))
(assert (= (process-wait proc1 #t) 0)))
(echo " world.")
(tr:do

View File

@ -81,7 +81,7 @@
;; Process management.
(define CLOSED_FD -1)
(define (call-with-fds what infd outfd errfd)
(wait-process (stringify what) (spawn-process-fd what infd outfd errfd) #t))
(process-wait (process-spawn-fd what infd outfd errfd) #t))
(define (call what)
(call-with-fds what
CLOSED_FD
@ -92,19 +92,19 @@
(define :stdin car)
(define :stdout cadr)
(define :stderr caddr)
(define :pid cadddr)
(define :proc cadddr)
(define (call-with-io what in)
(let ((h (spawn-process what 0)))
(let ((h (process-spawn what 0)))
(es-write (:stdin h) in)
(es-fclose (:stdin h))
(let* ((out (es-read-all (:stdout h)))
(err (es-read-all (:stderr h)))
(result (wait-process (car what) (:pid h) #t)))
(result (process-wait (:proc h) #t)))
(es-fclose (:stdout h))
(es-fclose (:stderr h))
(if (> (*verbose*) 2)
(info "Child" (:pid h) "returned:"
(info "Child" (:proc h) "returned:"
`((command ,(stringify what))
(status ,result)
(stdout ,out)
@ -351,12 +351,8 @@
(define (dump)
(write (list procs source sink producer))
(newline))
(define (add-proc command pid)
(new (cons (list command pid) procs) source sink producer))
(define (commands)
(map car procs))
(define (pids)
(map cadr procs))
(define (add-proc proc)
(new (cons proc procs) source sink producer))
(define (set-source source')
(new procs source' sink producer))
(define (set-sink sink')
@ -367,17 +363,19 @@
(new procs source sink producer'))))))
(define (process-wait-list procs hang)
(map (lambda (p) (process-wait p hang)) procs))
(define (pipe:do . commands)
(let loop ((M (pipeM::new '() CLOSED_FD CLOSED_FD #f)) (cmds commands))
(if (null? cmds)
(begin
(if M::producer (M::producer))
(if (not (null? M::procs))
(let* ((retcodes (wait-processes (map stringify (M::commands))
(M::pids) #t))
(results (map (lambda (p r) (append p (list r)))
(let* ((retcodes (process-wait-list M::procs #t))
(results (map (lambda (p r) (cons p r))
M::procs retcodes))
(failed (filter (lambda (x) (not (= 0 (caddr x))))
(failed (filter (lambda (x) (not (= 0 (cdr x))))
results)))
(if (not (null? failed))
(throw failed))))) ; xxx nicer reporting
@ -408,11 +406,11 @@
(define (pipe:spawn command)
(lambda (M)
(define (do-spawn M new-source)
(let ((pid (spawn-process-fd command M::source M::sink
(if (> (*verbose*) 0)
STDERR_FILENO CLOSED_FD)))
(let ((proc (process-spawn-fd command M::source M::sink
(if (> (*verbose*) 0)
STDERR_FILENO CLOSED_FD)))
(M' (M::set-source new-source)))
(M'::add-proc command pid)))
(M'::add-proc proc)))
(if (= CLOSED_FD M::sink)
(let* ((p (pipe))
(M' (do-spawn (M::set-sink (:write-end p)) (:read-end p))))
@ -568,8 +566,8 @@
(assert (= (length enqueued) (- i 1)))
test)))))
(define (pid->test pid)
(let ((t (filter (lambda (x) (= pid x::pid)) procs)))
(define (proc->test proc)
(let ((t (filter (lambda (x) (eq? proc x::proc)) procs)))
(if (null? t) #f (car t))))
(define (wait)
(if (null? enqueued)
@ -587,7 +585,7 @@
(if (null? unfinished)
(current-environment)
(let ((names (map (lambda (t) t::name) unfinished))
(pids (map (lambda (t) t::pid) unfinished))
(procs (map (lambda (t) t::proc) unfinished))
(any #f))
(for-each
(lambda (test retcode)
@ -597,8 +595,8 @@
(test::report)
(sem::release!)
(set! any #t)))
(map pid->test pids)
(wait-processes (map stringify names) pids hang))
(map proc->test procs)
(process-wait-list procs hang))
;; If some processes finished, try to start new ones.
(let loop ()
@ -682,7 +680,7 @@
(define (scm setup variant name path . args)
;; Start the process.
(define (spawn-scm args' in out err)
(spawn-process-fd `(,*argv0* ,@(verbosity (*verbose*))
(process-spawn-fd `(,*argv0* ,@(verbosity (*verbose*))
,(locate-test (test-name path))
,@(if setup (force setup) '())
,@args' ,@args) in out err))
@ -691,12 +689,12 @@
(define (binary setup name path . args)
;; Start the process.
(define (spawn-binary args' in out err)
(spawn-process-fd `(,(test-name path)
(process-spawn-fd `(,(test-name path)
,@(if setup (force setup) '()) ,@args' ,@args)
in out err))
(new #f name #f spawn-binary #f #f CLOSED_FD (expect-failure? name)))
(define (new variant name directory spawn pid retcode logfd expect-failure)
(define (new variant name directory spawn proc retcode logfd expect-failure)
(package
;; XXX: OO glue.
@ -721,7 +719,7 @@
;; Has the test been started yet?
(define (started?)
(number? pid))
proc)
(define (open-log-file)
(unless log-file-name
@ -738,26 +736,26 @@
(letfd ((log (open-log-file)))
(with-working-directory directory
(let* ((p (inbound-pipe))
(pid' (spawn args 0 (:write-end p) (:write-end p))))
(proc' (spawn args 0 (:write-end p) (:write-end p))))
(close (:write-end p))
(splice (:read-end p) STDERR_FILENO log)
(close (:read-end p))
(set! pid pid')
(set! retcode (wait-process name pid' #t)))))
(set! proc proc')
(set! retcode (process-wait proc' #t)))))
(report)
(current-environment))
(define (run-sync-quiet . args)
(set-start-time!)
(with-working-directory directory
(set! pid (spawn args CLOSED_FD CLOSED_FD CLOSED_FD)))
(set! retcode (wait-process name pid #t))
(set! proc (spawn args CLOSED_FD CLOSED_FD CLOSED_FD)))
(set! retcode (process-wait proc #t))
(set-end-time!)
(current-environment))
(define (run-async . args)
(set-start-time!)
(let ((log (open-log-file)))
(with-working-directory directory
(set! pid (spawn args CLOSED_FD log log)))
(set! proc (spawn args CLOSED_FD log log)))
(set! logfd log))
(current-environment))
(define (status)

View File

@ -268,13 +268,14 @@
(define (gpg-pipe args0 args1 errfd)
(lambda (source sink)
(let* ((p (pipe))
(task0 (spawn-process-fd `(,@GPG ,@args0)
(task0 (process-spawn-fd `(,@GPG ,@args0)
source (:write-end p) errfd))
(_ (close (:write-end p)))
(task1 (spawn-process-fd `(,@GPG ,@args1)
(task1 (process-spawn-fd `(,@GPG ,@args1)
(:read-end p) sink errfd)))
(close (:read-end p))
(wait-processes (list GPG GPG) (list task0 task1) #t))))
(process-wait task0 #t)
(process-wait task1 #t))))
(setenv "GPG_AGENT_INFO" "" #t)
(setenv "GNUPGHOME" (getcwd) #t)

View File

@ -217,13 +217,14 @@
(define (gpg-pipe args0 args1 errfd)
(lambda (source sink)
(let* ((p (pipe))
(task0 (spawn-process-fd `(,@GPG ,@args0)
(task0 (process-spawn-fd `(,@GPG ,@args0)
source (:write-end p) errfd))
(_ (close (:write-end p)))
(task1 (spawn-process-fd `(,@GPG ,@args1)
(task1 (process-spawn-fd `(,@GPG ,@args1)
(:read-end p) sink errfd)))
(close (:read-end p))
(wait-processes (list GPG GPG) (list task0 task1) #t))))
(process-wait task0 #t)
(process-wait task1 #t))))
;;
;; Do we have a software tpm

View File

@ -3641,7 +3641,7 @@ cmd_gpg (card_info_t info, char *argstr, int use_gpgsm)
char **argarray;
ccparray_t ccp;
const char **argv = NULL;
pid_t pid;
gnupg_process_t proc;
int i;
if (!info)
@ -3669,15 +3669,15 @@ cmd_gpg (card_info_t info, char *argstr, int use_gpgsm)
goto leave;
}
err = gnupg_spawn_process (use_gpgsm? opt.gpgsm_program:opt.gpg_program,
argv, NULL, (GNUPG_SPAWN_KEEP_STDOUT
|GNUPG_SPAWN_KEEP_STDERR),
NULL, NULL, NULL, &pid);
err = gnupg_process_spawn (use_gpgsm? opt.gpgsm_program:opt.gpg_program,
argv,
(GNUPG_PROCESS_STDOUT_KEEP
| GNUPG_PROCESS_STDERR_KEEP),
NULL, NULL, &proc);
if (!err)
{
err = gnupg_wait_process (use_gpgsm? opt.gpgsm_program:opt.gpg_program,
pid, 1, NULL);
gnupg_release_process (pid);
err = gnupg_process_wait (proc, 1);
gnupg_process_release (proc);
}

View File

@ -744,7 +744,7 @@ gpg_agent_runtime_change (int killflag)
gpg_error_t err = 0;
const char *pgmname;
const char *argv[5];
pid_t pid = (pid_t)(-1);
gnupg_process_t proc = NULL;
int i = 0;
int cmdidx;
@ -761,13 +761,13 @@ gpg_agent_runtime_change (int killflag)
log_assert (i < DIM(argv));
if (!err)
err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid);
err = gnupg_process_spawn (pgmname, argv, 0, NULL, NULL, &proc);
if (!err)
err = gnupg_wait_process (pgmname, pid, 1, NULL);
err = gnupg_process_wait (proc, 1);
if (err)
gc_error (0, 0, "error running '%s %s': %s",
pgmname, argv[cmdidx], gpg_strerror (err));
gnupg_release_process (pid);
gnupg_process_release (proc);
}
@ -777,7 +777,7 @@ scdaemon_runtime_change (int killflag)
gpg_error_t err = 0;
const char *pgmname;
const char *argv[9];
pid_t pid = (pid_t)(-1);
gnupg_process_t proc = NULL;
int i = 0;
int cmdidx;
@ -805,13 +805,13 @@ scdaemon_runtime_change (int killflag)
log_assert (i < DIM(argv));
if (!err)
err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid);
err = gnupg_process_spawn (pgmname, argv, 0, NULL, NULL, &proc);
if (!err)
err = gnupg_wait_process (pgmname, pid, 1, NULL);
err = gnupg_process_wait (proc, 1);
if (err)
gc_error (0, 0, "error running '%s %s': %s",
pgmname, argv[cmdidx], gpg_strerror (err));
gnupg_release_process (pid);
gnupg_process_release (proc);
}
@ -822,7 +822,7 @@ tpm2daemon_runtime_change (int killflag)
gpg_error_t err = 0;
const char *pgmname;
const char *argv[9];
pid_t pid = (pid_t)(-1);
gnupg_process_t proc = NULL;
int i = 0;
int cmdidx;
@ -850,13 +850,13 @@ tpm2daemon_runtime_change (int killflag)
log_assert (i < DIM(argv));
if (!err)
err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid);
err = gnupg_process_spawn (pgmname, argv, 0, NULL, NULL, &proc);
if (!err)
err = gnupg_wait_process (pgmname, pid, 1, NULL);
err = gnupg_process_wait (proc, 1);
if (err)
gc_error (0, 0, "error running '%s %s': %s",
pgmname, argv[cmdidx], gpg_strerror (err));
gnupg_release_process (pid);
gnupg_process_release (proc);
}
#endif
@ -867,7 +867,7 @@ dirmngr_runtime_change (int killflag)
gpg_error_t err = 0;
const char *pgmname;
const char *argv[6];
pid_t pid = (pid_t)(-1);
gnupg_process_t proc = NULL;
int i = 0;
int cmdidx;
@ -885,13 +885,13 @@ dirmngr_runtime_change (int killflag)
log_assert (i < DIM(argv));
if (!err)
err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid);
err = gnupg_process_spawn (pgmname, argv, 0, NULL, NULL, &proc);
if (!err)
err = gnupg_wait_process (pgmname, pid, 1, NULL);
err = gnupg_process_wait (proc, 1);
if (err)
gc_error (0, 0, "error running '%s %s': %s",
pgmname, argv[cmdidx], gpg_strerror (err));
gnupg_release_process (pid);
gnupg_process_release (proc);
}
@ -901,7 +901,7 @@ keyboxd_runtime_change (int killflag)
gpg_error_t err = 0;
const char *pgmname;
const char *argv[6];
pid_t pid = (pid_t)(-1);
gnupg_process_t proc = NULL;
int i = 0;
int cmdidx;
@ -919,13 +919,13 @@ keyboxd_runtime_change (int killflag)
log_assert (i < DIM(argv));
if (!err)
err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid);
err = gnupg_process_spawn (pgmname, argv, 0, NULL, NULL, &proc);
if (!err)
err = gnupg_wait_process (pgmname, pid, 1, NULL);
err = gnupg_process_wait (proc, 1);
if (err)
gc_error (0, 0, "error running '%s %s': %s",
pgmname, argv[cmdidx], gpg_strerror (err));
gnupg_release_process (pid);
gnupg_process_release (proc);
}
@ -937,7 +937,7 @@ gc_component_launch (int component)
const char *pgmname;
const char *argv[6];
int i;
pid_t pid;
gnupg_process_t proc = NULL;
if (component < 0)
{
@ -985,9 +985,9 @@ gc_component_launch (int component)
argv[i] = NULL;
log_assert (i < DIM(argv));
err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid);
err = gnupg_process_spawn (pgmname, argv, 0, NULL, NULL, &proc);
if (!err)
err = gnupg_wait_process (pgmname, pid, 1, NULL);
err = gnupg_process_wait (proc, 1);
if (err)
gc_error (0, 0, "error running '%s%s%s': %s",
pgmname,
@ -995,7 +995,7 @@ gc_component_launch (int component)
: component == GC_COMPONENT_KEYBOXD? " --keyboxd":"",
" NOP",
gpg_strerror (err));
gnupg_release_process (pid);
gnupg_process_release (proc);
return err;
}
@ -1336,8 +1336,7 @@ gc_component_check_options (int component, estream_t out, const char *conf_file)
const char *pgmname;
const char *argv[6];
int i;
pid_t pid;
int exitcode;
gnupg_process_t proc;
estream_t errfp;
error_line_t errlines;
@ -1370,22 +1369,28 @@ gc_component_check_options (int component, estream_t out, const char *conf_file)
result = 0;
errlines = NULL;
err = gnupg_spawn_process (pgmname, argv, NULL, 0,
NULL, NULL, &errfp, &pid);
err = gnupg_process_spawn (pgmname, argv,
GNUPG_PROCESS_STDERR_PIPE,
NULL, NULL, &proc);
if (err)
result |= 1; /* Program could not be run. */
else
{
gnupg_process_get_streams (proc, 0, NULL, NULL, &errfp);
errlines = collect_error_output (errfp,
gc_component[component].name);
if (gnupg_wait_process (pgmname, pid, 1, &exitcode))
if (!gnupg_process_wait (proc, 1))
{
int exitcode;
gnupg_process_ctl (proc, GNUPG_PROCESS_GET_EXIT_ID, &exitcode);
if (exitcode == -1)
result |= 1; /* Program could not be run or it
terminated abnormally. */
result |= 2; /* Program returned an error. */
else if (exitcode)
result |= 2; /* Program returned an error. */
}
gnupg_release_process (pid);
gnupg_process_release (proc);
es_fclose (errfp);
}
@ -1725,8 +1730,7 @@ retrieve_options_from_program (gc_component_id_t component, int only_installed)
const char *pgmname;
const char *argv[2];
estream_t outfp;
int exitcode;
pid_t pid;
gnupg_process_t proc;
known_option_t *known_option;
gc_option_t *option;
char *line = NULL;
@ -1759,14 +1763,17 @@ retrieve_options_from_program (gc_component_id_t component, int only_installed)
/* First we need to read the option table from the program. */
argv[0] = "--dump-option-table";
argv[1] = NULL;
err = gnupg_spawn_process (pgmname, argv, NULL, 0,
NULL, &outfp, NULL, &pid);
err = gnupg_process_spawn (pgmname, argv,
GNUPG_PROCESS_STDOUT_PIPE,
NULL, NULL, &proc);
if (err)
{
gc_error (1, 0, "could not gather option table from '%s': %s",
pgmname, gpg_strerror (err));
}
gnupg_process_get_streams (proc, 0, NULL, &outfp, NULL);
read_line_parm.pgmname = pgmname;
read_line_parm.fp = outfp;
read_line_parm.line = line;
@ -1925,12 +1932,17 @@ retrieve_options_from_program (gc_component_id_t component, int only_installed)
line_len = read_line_parm.line_len;
log_assert (opt_table_used + pseudo_count == opt_info_used);
err = gnupg_process_wait (proc, 1);
if (!err)
{
int exitcode;
err = gnupg_wait_process (pgmname, pid, 1, &exitcode);
if (err)
gc_error (1, 0, "running %s failed (exitcode=%d): %s",
pgmname, exitcode, gpg_strerror (err));
gnupg_release_process (pid);
gnupg_process_ctl (proc, GNUPG_PROCESS_GET_EXIT_ID, &exitcode);
if (exitcode)
gc_error (1, 0, "running %s failed (exitcode=%d): %s",
pgmname, exitcode, gpg_strerror (err));
}
gnupg_process_release (proc);
/* Make the gpgrt option table and the internal option table available. */
gc_component[component].opt_table = opt_table;
@ -1940,14 +1952,17 @@ retrieve_options_from_program (gc_component_id_t component, int only_installed)
/* Now read the default options. */
argv[0] = "--gpgconf-list";
argv[1] = NULL;
err = gnupg_spawn_process (pgmname, argv, NULL, 0,
NULL, &outfp, NULL, &pid);
err = gnupg_process_spawn (pgmname, argv,
GNUPG_PROCESS_STDOUT_PIPE,
NULL, NULL, &proc);
if (err)
{
gc_error (1, 0, "could not gather active options from '%s': %s",
pgmname, gpg_strerror (err));
}
gnupg_process_get_streams (proc, 0, NULL, &outfp, NULL);
while ((length = es_read_line (outfp, &line, &line_len, NULL)) > 0)
{
char *linep;
@ -2030,11 +2045,17 @@ retrieve_options_from_program (gc_component_id_t component, int only_installed)
if (es_fclose (outfp))
gc_error (1, errno, "error closing %s", pgmname);
err = gnupg_wait_process (pgmname, pid, 1, &exitcode);
if (err)
gc_error (1, 0, "running %s failed (exitcode=%d): %s",
pgmname, exitcode, gpg_strerror (err));
gnupg_release_process (pid);
err = gnupg_process_wait (proc, 1);
if (!err)
{
int exitcode;
gnupg_process_ctl (proc, GNUPG_PROCESS_GET_EXIT_ID, &exitcode);
if (exitcode)
gc_error (1, 0, "running %s failed (exitcode=%d): %s",
pgmname, exitcode, gpg_strerror (err));
}
gnupg_process_release (proc);
/* At this point, we can parse the configuration file. */

View File

@ -1173,17 +1173,17 @@ show_versions_via_dirmngr (estream_t fp)
const char *pgmname;
const char *argv[2];
estream_t outfp;
pid_t pid;
gnupg_process_t proc;
char *line = NULL;
size_t line_len = 0;
ssize_t length;
int exitcode;
pgmname = gnupg_module_name (GNUPG_MODULE_NAME_DIRMNGR);
argv[0] = "--gpgconf-versions";
argv[1] = NULL;
err = gnupg_spawn_process (pgmname, argv, NULL, 0,
NULL, &outfp, NULL, &pid);
err = gnupg_process_spawn (pgmname, argv,
GNUPG_PROCESS_STDOUT_PIPE,
NULL, NULL, &proc);
if (err)
{
log_error ("error spawning %s: %s", pgmname, gpg_strerror (err));
@ -1191,6 +1191,7 @@ show_versions_via_dirmngr (estream_t fp)
return;
}
gnupg_process_get_streams (proc, 0, NULL, &outfp, NULL);
while ((length = es_read_line (outfp, &line, &line_len, NULL)) > 0)
{
/* Strip newline and carriage return, if present. */
@ -1211,14 +1212,17 @@ show_versions_via_dirmngr (estream_t fp)
pgmname, gpg_strerror (err));
}
err = gnupg_wait_process (pgmname, pid, 1, &exitcode);
if (err)
err = gnupg_process_wait (proc, 1);
if (!err)
{
int exitcode;
gnupg_process_ctl (proc, GNUPG_PROCESS_GET_EXIT_ID, &exitcode);
log_error ("running %s failed (exitcode=%d): %s\n",
pgmname, exitcode, gpg_strerror (err));
es_fprintf (fp, "[error: can't get further info]\n");
}
gnupg_release_process (pid);
gnupg_process_release (proc);
xfree (line);
}

View File

@ -1069,7 +1069,7 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names,
estream_t files_from_stream = NULL;
estream_t outstream = NULL;
int eof_seen = 0;
pid_t pid = (pid_t)(-1);
gnupg_process_t proc = NULL;
unsigned int skipped_open = 0;
memset (scanctrl, 0, sizeof *scanctrl);
@ -1284,14 +1284,15 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names,
goto leave;
}
err = gnupg_spawn_process (opt.gpg_program, argv,
except[0] == -1? NULL : except,
(GNUPG_SPAWN_KEEP_STDOUT
| GNUPG_SPAWN_KEEP_STDERR),
&outstream, NULL, NULL, &pid);
err = gnupg_process_spawn (opt.gpg_program, argv,
(GNUPG_PROCESS_STDIN_PIPE
| GNUPG_PROCESS_STDOUT_KEEP
| GNUPG_PROCESS_STDERR_KEEP),
gnupg_spawn_helper, except, &proc);
xfree (argv);
if (err)
goto leave;
gnupg_process_get_streams (proc, 0, &outstream, NULL, NULL);
es_set_binary (outstream);
}
else if (opt.outfile) /* No crypto */
@ -1330,23 +1331,25 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names,
write_progress (1, global_written_files, global_total_files);
write_progress (0, global_written_data, global_total_data);
if (pid != (pid_t)(-1))
if (proc)
{
int exitcode;
err = es_fclose (outstream);
outstream = NULL;
if (err)
log_error ("error closing pipe: %s\n", gpg_strerror (err));
else
err = gnupg_process_wait (proc, 1);
if (!err)
{
err = gnupg_wait_process (opt.gpg_program, pid, 1, &exitcode);
if (err)
int exitcode;
gnupg_process_ctl (proc, GNUPG_PROCESS_GET_EXIT_ID, &exitcode);
if (exitcode)
log_error ("running %s failed (exitcode=%d): %s",
opt.gpg_program, exitcode, gpg_strerror (err));
gnupg_release_process (pid);
pid = (pid_t)(-1);
}
gnupg_process_release (proc);
proc = NULL;
}
if (skipped_open)
@ -1359,7 +1362,7 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names,
if (!err)
{
gpg_error_t first_err;
if (outstream != es_stdout || pid != (pid_t)(-1))
if (outstream != es_stdout)
first_err = es_fclose (outstream);
else
first_err = es_fflush (outstream);

View File

@ -339,7 +339,7 @@ gpgtar_extract (const char *filename, int decrypt)
char *dirname = NULL;
struct tarinfo_s tarinfo_buffer;
tarinfo_t tarinfo = &tarinfo_buffer;
pid_t pid = (pid_t)(-1);
gnupg_process_t proc;
char *logfilename = NULL;
unsigned long long notextracted;
@ -425,14 +425,14 @@ gpgtar_extract (const char *filename, int decrypt)
goto leave;
}
err = gnupg_spawn_process (opt.gpg_program, argv,
except[0] == -1? NULL : except,
((filename? 0 : GNUPG_SPAWN_KEEP_STDIN)
| GNUPG_SPAWN_KEEP_STDERR),
NULL, &stream, NULL, &pid);
err = gnupg_process_spawn (opt.gpg_program, argv,
((filename ? 0 : GNUPG_PROCESS_STDIN_KEEP)
| GNUPG_PROCESS_STDOUT_PIPE),
gnupg_spawn_helper, except, &proc);
xfree (argv);
if (err)
goto leave;
gnupg_process_get_streams (proc, 0, NULL, &stream, NULL);
es_set_binary (stream);
}
else if (filename)
@ -472,23 +472,25 @@ gpgtar_extract (const char *filename, int decrypt)
header = NULL;
}
if (pid != (pid_t)(-1))
if (proc)
{
int exitcode;
err = es_fclose (stream);
stream = NULL;
if (err)
log_error ("error closing pipe: %s\n", gpg_strerror (err));
else
err = gnupg_process_wait (proc, 1);
if (!err)
{
err = gnupg_wait_process (opt.gpg_program, pid, 1, &exitcode);
if (err)
int exitcode;
gnupg_process_ctl (proc, GNUPG_PROCESS_GET_EXIT_ID, &exitcode);
if (exitcode)
log_error ("running %s failed (exitcode=%d): %s",
opt.gpg_program, exitcode, gpg_strerror (err));
gnupg_release_process (pid);
pid = (pid_t)(-1);
}
gnupg_process_release (proc);
proc = NULL;
}
leave:

View File

@ -460,7 +460,7 @@ gpgtar_list (const char *filename, int decrypt)
strlist_t extheader = NULL;
struct tarinfo_s tarinfo_buffer;
tarinfo_t tarinfo = &tarinfo_buffer;
pid_t pid = (pid_t)(-1);
gnupg_process_t proc = NULL;
memset (&tarinfo_buffer, 0, sizeof tarinfo_buffer);
@ -503,14 +503,14 @@ gpgtar_list (const char *filename, int decrypt)
goto leave;
}
err = gnupg_spawn_process (opt.gpg_program, argv,
except[0] == -1? NULL : except,
((filename? 0 : GNUPG_SPAWN_KEEP_STDIN)
| GNUPG_SPAWN_KEEP_STDERR),
NULL, &stream, NULL, &pid);
err = gnupg_process_spawn (opt.gpg_program, argv,
((filename ? 0 : GNUPG_PROCESS_STDIN_KEEP)
| GNUPG_PROCESS_STDOUT_PIPE),
gnupg_spawn_helper, except, &proc);
xfree (argv);
if (err)
goto leave;
gnupg_process_get_streams (proc, 0, NULL, &stream, NULL);
es_set_binary (stream);
}
else if (filename) /* No decryption requested. */
@ -550,23 +550,24 @@ gpgtar_list (const char *filename, int decrypt)
header = NULL;
}
if (pid != (pid_t)(-1))
if (proc)
{
int exitcode;
err = es_fclose (stream);
stream = NULL;
if (err)
log_error ("error closing pipe: %s\n", gpg_strerror (err));
else
err = gnupg_process_wait (proc, 1);
if (!err)
{
err = gnupg_wait_process (opt.gpg_program, pid, 1, &exitcode);
if (err)
log_error ("running %s failed (exitcode=%d): %s",
opt.gpg_program, exitcode, gpg_strerror (err));
gnupg_release_process (pid);
pid = (pid_t)(-1);
int exitcode;
gnupg_process_ctl (proc, GNUPG_PROCESS_GET_EXIT_ID, &exitcode);
log_error ("running %s failed (exitcode=%d): %s",
opt.gpg_program, exitcode, gpg_strerror (err));
}
gnupg_process_release (proc);
proc = NULL;
}
leave: