* 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.
+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
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.
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
#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. ******/
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
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.
/* 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,
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;
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;
}
}
- 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,
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)
}
+#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)
{
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);
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,
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);
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,
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
/* 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,
}
+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)
{
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);
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;
}
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);
}
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"
\f
_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)
}
return count;
}
+
+\f
+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;
+}
+
+
/* Member functions. */
gpg_release,
+ NULL, /* reset */
gpg_set_status_handler,
gpg_set_command_handler,
gpg_set_colon_line_handler,