2006-12-17 Marcus Brinkmann <marcus@g10code.de>
* configure.ac: Fix two typos in last change. gpgme/ 2006-12-17 Marcus Brinkmann <marcus@g10code.de> * gpgme.c (gpgme_set_protocol): Shut down the engine when switching protocols. (gpgme_ctx_set_engine_info): Likewise for engine info. * engine.h (_gpgme_engine_reset): New function prototype. * engine.c (_gpgme_engine_reset): New function. * engine-backend.h (struct engine_ops): New member RESET. * rungpg.c (_gpgme_engine_ops_gpg): Add NULL for reset function. * engine-gpgsm.c (_gpgme_engine_ops_gpgsm) [USE_DESCRIPTOR_PASSING]: Add gpgsm_reset for reset. (_gpgme_engine_ops_gpgsm) [!USE_DESCRIPTOR_PASSING]: Add NULL for reset function. (gpgsm_reset) [USE_DESCRIPTOR_PASSING]: New function. * op-support.c (_gpgme_op_reset): Try to use the engine's reset function if available. * engine-gpgsm.c (gpgsm_new): Move code to dup status_fd to ... (start): ... here. * posix-io.c (_gpgme_io_recvmsg, _gpgme_io_sendmsg): New functions.
This commit is contained in:
parent
f9bf0d5b79
commit
13d2e5d1c7
@ -1,3 +1,7 @@
|
||||
2006-12-17 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* configure.ac: Fix two typos in last change.
|
||||
|
||||
2006-12-03 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* configure.ac: Use descriptor passing only if --enable-fd-passing
|
||||
|
2
TODO
2
TODO
@ -78,6 +78,8 @@ Hey Emacs, this is -*- outline -*- mode!
|
||||
release everything properly at a reset and at an error. Think hard
|
||||
about where to guarantee what (ie, what happens if start fails, are
|
||||
the fds unregistered immediately - i think so?)
|
||||
Note that we need support in gpgsm to set include-certs to default
|
||||
as RESET does not reset it.
|
||||
** Optimize the case where a data object has 0an underlying fd we can pass
|
||||
directly to the engine. This will be automatic with socket I/O and
|
||||
descriptor passing.
|
||||
|
@ -75,6 +75,8 @@ int _gpgme_ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr);
|
||||
int _gpgme_ath_connect (int s, struct sockaddr *addr, socklen_t length);
|
||||
int _gpgme_ath_sendmsg (int s, const struct msghdr *msg, int flags);
|
||||
int _gpgme_ath_recvmsg (int s, struct msghdr *msg, int flags);
|
||||
int _gpgme_io_sendmsg (int sock, const struct msghdr *msg, int flags);
|
||||
int _gpgme_io_recvmsg (int sock, struct msghdr *msg, int flags);
|
||||
#endif /*!HAVE_W32_SYSTEM*/
|
||||
|
||||
#define read _gpgme_io_read
|
||||
@ -83,8 +85,8 @@ int _gpgme_ath_recvmsg (int s, struct msghdr *msg, int flags);
|
||||
#define select _gpgme_ath_select
|
||||
#define accept _gpgme_ath_accept
|
||||
#define connect _gpgme_ath_connect
|
||||
#define sendmsg _gpgme_ath_sendmsg
|
||||
#define recvmsg _gpgme_ath_recvmsg
|
||||
#define sendmsg _gpgme_io_sendmsg
|
||||
#define recvmsg _gpgme_io_recvmsg
|
||||
#endif /*_ASSUAN_IN_GPGME_BUILD_ASSUAN*/
|
||||
/**** End GPGME specific modifications. ******/
|
||||
|
||||
|
@ -491,7 +491,7 @@ AC_CHECK_MEMBER(struct cmsghdr.cmsg_len,
|
||||
|
||||
AC_ARG_ENABLE(fd-passing,
|
||||
AC_HELP_STRING([--enable-fd-passing], [use FD passing if supported]),
|
||||
use_desciptor_passing=$withval)
|
||||
use_descriptor_passing=$enableval)
|
||||
|
||||
if test "$supports_descriptor_passing" != "yes"; then
|
||||
use_descriptor_passing=no
|
||||
|
@ -1,5 +1,23 @@
|
||||
2006-12-17 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* gpgme.c (gpgme_set_protocol): Shut down the engine when
|
||||
switching protocols.
|
||||
(gpgme_ctx_set_engine_info): Likewise for engine info.
|
||||
* engine.h (_gpgme_engine_reset): New function prototype.
|
||||
* engine.c (_gpgme_engine_reset): New function.
|
||||
* engine-backend.h (struct engine_ops): New member RESET.
|
||||
* rungpg.c (_gpgme_engine_ops_gpg): Add NULL for reset function.
|
||||
* engine-gpgsm.c (_gpgme_engine_ops_gpgsm)
|
||||
[USE_DESCRIPTOR_PASSING]: Add gpgsm_reset for reset.
|
||||
(_gpgme_engine_ops_gpgsm) [!USE_DESCRIPTOR_PASSING]: Add NULL for
|
||||
reset function.
|
||||
(gpgsm_reset) [USE_DESCRIPTOR_PASSING]: New function.
|
||||
* op-support.c (_gpgme_op_reset): Try to use the engine's reset
|
||||
function if available.
|
||||
* engine-gpgsm.c (gpgsm_new): Move code to dup status_fd to ...
|
||||
(start): ... here.
|
||||
* posix-io.c (_gpgme_io_recvmsg, _gpgme_io_sendmsg): New functions.
|
||||
|
||||
* engine.h (_gpgme_engine_new): Remove arguments lc_ctype and
|
||||
lc_messages from prototype.
|
||||
(_gpgme_engine_set_locale): New prototype.
|
||||
|
@ -49,6 +49,7 @@ struct engine_ops
|
||||
|
||||
/* Member functions. */
|
||||
void (*release) (void *engine);
|
||||
gpgme_error_t (*reset) (void *engine);
|
||||
void (*set_status_handler) (void *engine, engine_status_handler_t fnc,
|
||||
void *fnc_value);
|
||||
gpgme_error_t (*set_command_handler) (void *engine,
|
||||
|
@ -334,15 +334,15 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir)
|
||||
char dft_ttyname[64];
|
||||
char *dft_ttytype = NULL;
|
||||
char *optstr;
|
||||
int fdlist[5];
|
||||
int nfds;
|
||||
|
||||
gpgsm = calloc (1, sizeof *gpgsm);
|
||||
if (!gpgsm)
|
||||
return gpg_error_from_errno (errno);
|
||||
|
||||
gpgsm->status_cb.fd = -1;
|
||||
gpgsm->status_cb.dir = 1;
|
||||
gpgsm->status_cb.tag = 0;
|
||||
gpgsm->status_cb.data = gpgsm;
|
||||
|
||||
gpgsm->input_cb.fd = -1;
|
||||
gpgsm->input_cb.dir = 0;
|
||||
@ -423,30 +423,6 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir)
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
/* We need to know the fd used by assuan for reads. We do this by
|
||||
using the assumption that the first returned fd from
|
||||
assuan_get_active_fds() is always this one. */
|
||||
nfds = assuan_get_active_fds (gpgsm->assuan_ctx, 0 /* read fds */,
|
||||
fdlist, DIM (fdlist));
|
||||
if (nfds < 1)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_GENERAL); /* FIXME */
|
||||
goto leave;
|
||||
}
|
||||
/* We duplicate the file descriptor, so we can close it without
|
||||
disturbing assuan. Alternatively, we could special case
|
||||
status_fd and register/unregister it manually as needed, but this
|
||||
increases code duplication and is more complicated as we can not
|
||||
use the close notifications etc. */
|
||||
gpgsm->status_cb.fd = dup (fdlist[0]);
|
||||
if (gpgsm->status_cb.fd < 0)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_GENERAL); /* FIXME */
|
||||
goto leave;
|
||||
}
|
||||
gpgsm->status_cb.dir = 1;
|
||||
gpgsm->status_cb.data = gpgsm;
|
||||
|
||||
err = _gpgme_getenv ("DISPLAY", &dft_display);
|
||||
if (err)
|
||||
goto leave;
|
||||
@ -518,14 +494,6 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir)
|
||||
}
|
||||
}
|
||||
|
||||
if (!err
|
||||
&& (_gpgme_io_set_close_notify (gpgsm->status_cb.fd,
|
||||
close_notify_handler, gpgsm)))
|
||||
{
|
||||
err = gpg_error (GPG_ERR_GENERAL);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
#if !USE_DESCRIPTOR_PASSING
|
||||
if (!err
|
||||
&& (_gpgme_io_set_close_notify (gpgsm->input_cb.fd,
|
||||
@ -997,6 +965,33 @@ static gpgme_error_t
|
||||
start (engine_gpgsm_t gpgsm, const char *command)
|
||||
{
|
||||
gpgme_error_t err;
|
||||
int fdlist[5];
|
||||
int nfds;
|
||||
|
||||
/* We need to know the fd used by assuan for reads. We do this by
|
||||
using the assumption that the first returned fd from
|
||||
assuan_get_active_fds() is always this one. */
|
||||
nfds = assuan_get_active_fds (gpgsm->assuan_ctx, 0 /* read fds */,
|
||||
fdlist, DIM (fdlist));
|
||||
if (nfds < 1)
|
||||
return gpg_error (GPG_ERR_GENERAL); /* FIXME */
|
||||
|
||||
/* We duplicate the file descriptor, so we can close it without
|
||||
disturbing assuan. Alternatively, we could special case
|
||||
status_fd and register/unregister it manually as needed, but this
|
||||
increases code duplication and is more complicated as we can not
|
||||
use the close notifications etc. */
|
||||
gpgsm->status_cb.fd = dup (fdlist[0]);
|
||||
if (gpgsm->status_cb.fd < 0)
|
||||
return gpg_error_from_syserror ();
|
||||
|
||||
if (_gpgme_io_set_close_notify (gpgsm->status_cb.fd,
|
||||
close_notify_handler, gpgsm))
|
||||
{
|
||||
close (gpgsm->status_cb.fd);
|
||||
gpgsm->status_cb.fd = -1;
|
||||
return gpg_error (GPG_ERR_GENERAL);
|
||||
}
|
||||
|
||||
err = add_io_cb (gpgsm, &gpgsm->status_cb, status_handler);
|
||||
if (!err && gpgsm->input_cb.fd != -1)
|
||||
@ -1016,6 +1011,19 @@ start (engine_gpgsm_t gpgsm, const char *command)
|
||||
}
|
||||
|
||||
|
||||
#if USE_DESCRIPTOR_PASSING
|
||||
static gpgme_error_t
|
||||
gpgsm_reset (void *engine)
|
||||
{
|
||||
engine_gpgsm_t gpgsm = engine;
|
||||
|
||||
/* We must send a reset because we need to reset the list of
|
||||
signers. Note that RESET does not reset OPTION commands. */
|
||||
return gpgsm_assuan_simple_command (gpgsm->assuan_ctx, "RESET", NULL, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static gpgme_error_t
|
||||
gpgsm_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain)
|
||||
{
|
||||
@ -1385,6 +1393,7 @@ gpgsm_keylist (void *engine, const char *pattern, int secret_only,
|
||||
if (!pattern)
|
||||
pattern = "";
|
||||
|
||||
/* Always send list-mode option because RESET does not reset it. */
|
||||
if (asprintf (&line, "OPTION list-mode=%d", (list_mode & 3)) < 0)
|
||||
return gpg_error_from_errno (errno);
|
||||
err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, line, NULL, NULL);
|
||||
@ -1393,6 +1402,8 @@ gpgsm_keylist (void *engine, const char *pattern, int secret_only,
|
||||
return err;
|
||||
|
||||
|
||||
/* Always send key validation because RESET does not reset it. */
|
||||
|
||||
/* Use the validation mode if required. We don't check for an error
|
||||
yet because this is a pretty fresh gpgsm features. */
|
||||
gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
|
||||
@ -1448,6 +1459,7 @@ gpgsm_keylist_ext (void *engine, const char *pattern[], int secret_only,
|
||||
if (mode & GPGME_KEYLIST_MODE_EXTERN)
|
||||
list_mode |= 2;
|
||||
|
||||
/* Always send list-mode option because RESET does not reset it. */
|
||||
if (asprintf (&line, "OPTION list-mode=%d", (list_mode & 3)) < 0)
|
||||
return gpg_error_from_errno (errno);
|
||||
err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, line, NULL, NULL);
|
||||
@ -1455,6 +1467,7 @@ gpgsm_keylist_ext (void *engine, const char *pattern[], int secret_only,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Always send key validation because RESET does not reset it. */
|
||||
/* Use the validation mode if required. We don't check for an error
|
||||
yet because this is a pretty fresh gpgsm features. */
|
||||
gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
|
||||
@ -1561,12 +1574,8 @@ gpgsm_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
|
||||
if (!gpgsm)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
/* We must send a reset because we need to reset the list of
|
||||
signers. Note that RESET does not reset OPTION commands. */
|
||||
err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, "RESET", NULL, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* FIXME: This does not work as RESET does not reset it so we can't
|
||||
revert back to default. */
|
||||
if (include_certs != GPGME_INCLUDE_CERTS_DEFAULT)
|
||||
{
|
||||
/* FIXME: Make sure that if we run multiple operations, that we
|
||||
@ -1704,6 +1713,11 @@ struct engine_ops _gpgme_engine_ops_gpgsm =
|
||||
|
||||
/* Member functions. */
|
||||
gpgsm_release,
|
||||
#if USE_DESCRIPTOR_PASSING
|
||||
gpgsm_reset,
|
||||
#else
|
||||
NULL, /* reset */
|
||||
#endif
|
||||
gpgsm_set_status_handler,
|
||||
NULL, /* set_command_handler */
|
||||
gpgsm_set_colon_line_handler,
|
||||
|
@ -420,6 +420,19 @@ _gpgme_engine_new (gpgme_engine_info_t info, engine_t *r_engine)
|
||||
}
|
||||
|
||||
|
||||
gpgme_error_t
|
||||
_gpgme_engine_reset (engine_t engine)
|
||||
{
|
||||
if (!engine)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
if (!engine->ops->reset)
|
||||
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||
|
||||
return (*engine->ops->reset) (engine->engine);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_gpgme_engine_release (engine_t engine)
|
||||
{
|
||||
|
@ -52,6 +52,7 @@ gpgme_error_t _gpgme_set_engine_info (gpgme_engine_info_t info,
|
||||
|
||||
gpgme_error_t _gpgme_engine_new (gpgme_engine_info_t info,
|
||||
engine_t *r_engine);
|
||||
gpgme_error_t _gpgme_engine_reset (engine_t engine);
|
||||
|
||||
gpgme_error_t _gpgme_engine_set_locale (engine_t engine, int category,
|
||||
const char *value);
|
||||
|
@ -159,7 +159,17 @@ gpgme_set_protocol (gpgme_ctx_t ctx, gpgme_protocol_t protocol)
|
||||
if (protocol != GPGME_PROTOCOL_OpenPGP && protocol != GPGME_PROTOCOL_CMS)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
ctx->protocol = protocol;
|
||||
if (ctx->protocol != protocol)
|
||||
{
|
||||
/* Shut down the engine when switching protocols. */
|
||||
if (ctx->engine)
|
||||
{
|
||||
_gpgme_engine_release (ctx->engine);
|
||||
ctx->engine = NULL;
|
||||
}
|
||||
|
||||
ctx->protocol = protocol;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -417,8 +427,12 @@ gpgme_error_t
|
||||
gpgme_ctx_set_engine_info (gpgme_ctx_t ctx, gpgme_protocol_t proto,
|
||||
const char *file_name, const char *home_dir)
|
||||
{
|
||||
/* FIXME: Make sure to reset the context if we are running in daemon
|
||||
mode. */
|
||||
/* Shut down the engine when changing engine info. */
|
||||
if (ctx->engine)
|
||||
{
|
||||
_gpgme_engine_release (ctx->engine);
|
||||
ctx->engine = NULL;
|
||||
}
|
||||
return _gpgme_set_engine_info (ctx->engine_info, proto,
|
||||
file_name, home_dir);
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ extern "C" {
|
||||
AM_PATH_GPGME macro) check that this header matches the installed
|
||||
library. Warning: Do not edit the next line. configure will do
|
||||
that for you! */
|
||||
#define GPGME_VERSION "1.1.3-cvs1188"
|
||||
#define GPGME_VERSION "1.1.3-cvs1196"
|
||||
|
||||
|
||||
|
||||
|
@ -68,28 +68,37 @@ gpgme_error_t
|
||||
_gpgme_op_reset (gpgme_ctx_t ctx, int type)
|
||||
{
|
||||
gpgme_error_t err = 0;
|
||||
gpgme_engine_info_t info;
|
||||
struct gpgme_io_cbs io_cbs;
|
||||
|
||||
info = ctx->engine_info;
|
||||
while (info && info->protocol != ctx->protocol)
|
||||
info = info->next;
|
||||
|
||||
if (!info)
|
||||
return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
|
||||
|
||||
_gpgme_release_result (ctx);
|
||||
|
||||
if (ctx->engine)
|
||||
{
|
||||
_gpgme_engine_release (ctx->engine);
|
||||
ctx->engine = NULL;
|
||||
/* Attempt to reset an existing engine. */
|
||||
|
||||
err = _gpgme_engine_reset (ctx->engine);
|
||||
if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
|
||||
{
|
||||
_gpgme_engine_release (ctx->engine);
|
||||
ctx->engine = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create an engine object. */
|
||||
err = _gpgme_engine_new (info, &ctx->engine);
|
||||
if (err)
|
||||
return err;
|
||||
if (!ctx->engine)
|
||||
{
|
||||
gpgme_engine_info_t info;
|
||||
info = ctx->engine_info;
|
||||
while (info && info->protocol != ctx->protocol)
|
||||
info = info->next;
|
||||
|
||||
if (!info)
|
||||
return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
|
||||
|
||||
/* Create an engine object. */
|
||||
err = _gpgme_engine_new (info, &ctx->engine);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = _gpgme_engine_set_locale (ctx->engine, LC_CTYPE, ctx->lc_ctype);
|
||||
if (!err)
|
||||
|
@ -412,3 +412,86 @@ _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_gpgme_io_recvmsg (int fd, struct msghdr *msg, int flags)
|
||||
{
|
||||
int nread;
|
||||
int saved_errno;
|
||||
struct iovec *iov;
|
||||
|
||||
nread = 0;
|
||||
iov = msg->msg_iov;
|
||||
while (iov < msg->msg_iov + msg->msg_iovlen)
|
||||
{
|
||||
nread += iov->iov_len;
|
||||
iov++;
|
||||
}
|
||||
|
||||
DEBUG2 ("fd %d: about to receive %d bytes\n",
|
||||
fd, (int) nread);
|
||||
do
|
||||
{
|
||||
nread = _gpgme_ath_recvmsg (fd, msg, flags);
|
||||
}
|
||||
while (nread == -1 && errno == EINTR);
|
||||
saved_errno = errno;
|
||||
DEBUG2 ("fd %d: got %d bytes\n", fd, nread);
|
||||
if (nread > 0)
|
||||
{
|
||||
int nr = nread;
|
||||
|
||||
iov = msg->msg_iov;
|
||||
while (nr > 0)
|
||||
{
|
||||
int len = nr > iov->iov_len ? iov->iov_len : nr;
|
||||
_gpgme_debug (2, "fd %d: got `%.*s'\n", fd, len,
|
||||
msg->msg_iov->iov_base);
|
||||
iov++;
|
||||
nr -= len;
|
||||
}
|
||||
}
|
||||
errno = saved_errno;
|
||||
return nread;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_gpgme_io_sendmsg (int fd, const struct msghdr *msg, int flags)
|
||||
{
|
||||
int saved_errno;
|
||||
int nwritten;
|
||||
struct iovec *iov;
|
||||
|
||||
nwritten = 0;
|
||||
iov = msg->msg_iov;
|
||||
while (iov < msg->msg_iov + msg->msg_iovlen)
|
||||
{
|
||||
nwritten += iov->iov_len;
|
||||
iov++;
|
||||
}
|
||||
|
||||
DEBUG2 ("fd %d: about to write %d bytes\n", fd, (int) nwritten);
|
||||
iov = msg->msg_iov;
|
||||
while (nwritten > 0)
|
||||
{
|
||||
int len = nwritten > iov->iov_len ? iov->iov_len : nwritten;
|
||||
_gpgme_debug (2, "fd %d: write `%.*s'\n", fd, len,
|
||||
msg->msg_iov->iov_base);
|
||||
iov++;
|
||||
nwritten -= len;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
nwritten = _gpgme_ath_sendmsg (fd, msg, flags);
|
||||
}
|
||||
while (nwritten == -1 && errno == EINTR);
|
||||
saved_errno = errno;
|
||||
DEBUG2 ("fd %d: wrote %d bytes\n", fd, (int) nwritten);
|
||||
errno = saved_errno;
|
||||
return nwritten;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2078,6 +2078,7 @@ struct engine_ops _gpgme_engine_ops_gpg =
|
||||
|
||||
/* Member functions. */
|
||||
gpg_release,
|
||||
NULL, /* reset */
|
||||
gpg_set_status_handler,
|
||||
gpg_set_command_handler,
|
||||
gpg_set_colon_line_handler,
|
||||
|
Loading…
Reference in New Issue
Block a user