mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
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:
parent
1e41878bf2
commit
a035938216
@ -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);
|
||||
|
@ -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
@ -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*/
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
||||
|
||||
|
36
g13/runner.c
36
g13/runner.c
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
21
scd/app.c
21
scd/app.c
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user