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:
Marcus Brinkmann 2006-12-17 21:12:40 +00:00
parent f9bf0d5b79
commit 13d2e5d1c7
14 changed files with 223 additions and 61 deletions

View File

@ -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
View File

@ -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.

View File

@ -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. ******/

View File

@ -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

View File

@ -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.

View File

@ -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,

View File

@ -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,

View File

@ -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)
{

View File

@ -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);

View File

@ -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);
}

View File

@ -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"

View File

@ -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)

View File

@ -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;
}

View File

@ -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,