* gpgme.c (gpgme_set_io_cbs): Deal with CTX being NULL.
* gpgme.c (_gpgme_op_event_cb_user): New function.
* op-support.c (_gpgme_op_reset): Support a new mode of operation
for private or user event loop. Use new user event callback
wrapper.
* trustlist.c (gpgme_op_trustlist_start): Use this new mode.
* keylist.c (gpgme_op_keylist_start): Likewise.
* rungpg.c (_gpgme_gpg_io_event): New function.
* rungpg.h (_gpgme_gpg_io_event): New prototype.
* engine-gpgsm.c (_gpgme_gpg_io_event): New function.
* engine-gpgsm.h (_gpgme_gpgsm_io_event): New prototype.
* engine.c (_gpgme_engine_io_event): New function.
* engine.h (_gpgme_engine_io_event): New prototype.
* keylist.c (finish_key): Call _gpgme_engine_io_event, and move
the real work for the default IO callback routines to ...
(_gpgme_op_keylist_event_cb): ... here. New function.
* trustlist.c (trustlist_colon_handler): Signal
GPGME_EVENT_NEXT_TRUSTITEM. Move queue manipulation to ...
(_gpgme_op_trustlist_event_cb): ... here. New function.
* gpgme.c (_gpgme_op_event_cb): Call _gpgme_op_keylist_event_cb
and _gpgme_op_trustlist_event_cb when appropriate.
* ops.h (_gpgme_op_keylist_event_cb): New prototype.
(_gpgme_op_trustlist_event_cb): Likewise.
* op-support.c (_gpgme_op_reset): Add comment why we don't use the
user provided event handler directly.
* gpgme.h (GpgmeRegisterIOCb): Return GpgmeError value, and TAG in
a pointer argument.
* wait.c (_gpgme_add_io_cb): Likewise.
* wait.h (_gpgme_add_io_cb): Likewise for prototype.
* rungpg.c (_gpgme_gpg_add_io_cb): Call IO_CBS->add with new
argument. Fix up error handling.
* engine-gpgsm.c (_gpgme_gpgsm_add_io_cb): Call IO_CBS->add with
new argument, fix up error handling.
+2002-07-03 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.c (gpgme_set_io_cbs): Deal with CTX being NULL.
+
+ * gpgme.c (_gpgme_op_event_cb_user): New function.
+ * op-support.c (_gpgme_op_reset): Support a new mode of operation
+ for private or user event loop. Use new user event callback
+ wrapper.
+ * trustlist.c (gpgme_op_trustlist_start): Use this new mode.
+ * keylist.c (gpgme_op_keylist_start): Likewise.
+
+ * rungpg.c (_gpgme_gpg_io_event): New function.
+ * rungpg.h (_gpgme_gpg_io_event): New prototype.
+ * engine-gpgsm.c (_gpgme_gpg_io_event): New function.
+ * engine-gpgsm.h (_gpgme_gpgsm_io_event): New prototype.
+ * engine.c (_gpgme_engine_io_event): New function.
+ * engine.h (_gpgme_engine_io_event): New prototype.
+ * keylist.c (finish_key): Call _gpgme_engine_io_event, and move
+ the real work for the default IO callback routines to ...
+ (_gpgme_op_keylist_event_cb): ... here. New function.
+ * trustlist.c (trustlist_colon_handler): Signal
+ GPGME_EVENT_NEXT_TRUSTITEM. Move queue manipulation to ...
+ (_gpgme_op_trustlist_event_cb): ... here. New function.
+ * gpgme.c (_gpgme_op_event_cb): Call _gpgme_op_keylist_event_cb
+ and _gpgme_op_trustlist_event_cb when appropriate.
+ * ops.h (_gpgme_op_keylist_event_cb): New prototype.
+ (_gpgme_op_trustlist_event_cb): Likewise.
+ * op-support.c (_gpgme_op_reset): Add comment why we don't use the
+ user provided event handler directly.
+ * gpgme.h (GpgmeRegisterIOCb): Return GpgmeError value, and TAG in
+ a pointer argument.
+ * wait.c (_gpgme_add_io_cb): Likewise.
+ * wait.h (_gpgme_add_io_cb): Likewise for prototype.
+ * rungpg.c (_gpgme_gpg_add_io_cb): Call IO_CBS->add with new
+ argument. Fix up error handling.
+ * engine-gpgsm.c (_gpgme_gpgsm_add_io_cb): Call IO_CBS->add with
+ new argument, fix up error handling.
+
2002-06-28 Marcus Brinkmann <marcus@g10code.de>
* keylist.c (gpgme_op_keylist_ext_start): Always use our own FD
_gpgme_gpgsm_add_io_cb (GpgsmObject gpgsm, iocb_data_t *iocbd,
GpgmeIOCb handler)
{
- GpgmeError err = 0;
+ GpgmeError err;
- iocbd->tag = (*gpgsm->io_cbs.add) (gpgsm->io_cbs.add_priv,
- iocbd->fd, iocbd->dir,
- handler, iocbd->data);
- if (!iocbd->tag)
- err = mk_error (General_Error);
- if (!err && !iocbd->dir)
+ err = (*gpgsm->io_cbs.add) (gpgsm->io_cbs.add_priv,
+ iocbd->fd, iocbd->dir,
+ handler, iocbd->data, &iocbd->tag);
+ if (err)
+ return err;
+ if (!iocbd->dir)
/* FIXME Kludge around poll() problem. */
err = _gpgme_io_set_nonblocking (iocbd->fd);
return err;
gpgsm->io_cbs = *io_cbs;
}
+void
+_gpgme_gpgsm_io_event (GpgsmObject gpgsm, GpgmeEventIO type, void *type_data)
+{
+ if (gpgsm->io_cbs.event)
+ (*gpgsm->io_cbs.event) (gpgsm->io_cbs.event_priv, type, type_data);
+}
#else /* ENABLE_GPGSM */
{
}
+void
+_gpgme_gpgsm_io_event (GpgsmObject gpgsm, GpgmeEventIO type, void *type_data)
+{
+}
+
#endif /* ! ENABLE_GPGSM */
GpgmeData text);
GpgmeError _gpgme_gpgsm_start (GpgsmObject gpgsm, void *opaque);
void _gpgme_gpgsm_set_io_cbs (GpgsmObject gpgsm, struct GpgmeIOCbs *io_cbs);
+void _gpgme_gpgsm_io_event (GpgsmObject gpgsm, GpgmeEventIO type, void *type_data);
#endif /* ENGINE_GPGSM_H */
}
}
+void
+_gpgme_engine_io_event (EngineObject engine,
+ GpgmeEventIO type, void *type_data)
+{
+ if (!engine)
+ return;
+
+ switch (engine->protocol)
+ {
+ case GPGME_PROTOCOL_OpenPGP:
+ _gpgme_gpg_io_event (engine->engine.gpg, type, type_data);
+ break;
+ case GPGME_PROTOCOL_CMS:
+ _gpgme_gpgsm_io_event (engine->engine.gpgsm, type, type_data);
+ break;
+ default:
+ break;
+ }
+}
+
\f
void
_gpgme_engine_add_child_to_reap_list (void *buf, int buflen, pid_t pid)
void _gpgme_engine_set_io_cbs (EngineObject engine,
struct GpgmeIOCbs *io_cbs);
+void _gpgme_engine_io_event (EngineObject engine,
+ GpgmeEventIO type, void *type_data);
void _gpgme_engine_add_child_to_reap_list (void *buf, int buflen, pid_t pid);
void _gpgme_engine_housecleaning (void);
void
gpgme_set_io_cbs (GpgmeCtx ctx, struct GpgmeIOCbs *io_cbs)
{
- if (ctx && io_cbs)
+ if (!ctx)
+ return;
+
+ if (io_cbs)
ctx->io_cbs = *io_cbs;
else
{
{
GpgmeCtx ctx = data;
- if (type == GPGME_EVENT_DONE)
- ctx->pending = 0;
+ switch (type)
+ {
+ case GPGME_EVENT_DONE:
+ ctx->pending = 0;
+ break;
+
+ case GPGME_EVENT_NEXT_KEY:
+ _gpgme_op_keylist_event_cb (data, type, type_data);
+ break;
- if (ctx->io_cbs.add && ctx->io_cbs.event)
- (*ctx->io_cbs.event) (ctx->io_cbs.event_priv, type, type_data);
+ case GPGME_EVENT_NEXT_TRUSTITEM:
+ _gpgme_op_trustlist_event_cb (data, type, type_data);
+ break;
+ }
+}
+
+void
+_gpgme_op_event_cb_user (void *data, GpgmeEventIO type, void *type_data)
+{
+ GpgmeCtx ctx = data;
+
+ if (type == GPGME_EVENT_DONE)
+ {
+ ctx->pending = 0;
+ if (ctx->io_cbs.event)
+ (*ctx->io_cbs.event) (ctx->io_cbs.event_priv, type, &ctx->error);
+ }
+ else
+ {
+ if (ctx->io_cbs.event)
+ (*ctx->io_cbs.event) (ctx->io_cbs.event_priv, type, type_data);
+ }
}
typedef void (*GpgmeIOCb) (void *data, int fd);
/* The type of a function that can register FNC as the I/O callback
- function for the file descriptor FD with direction dir (0: inbound,
- 1: outbound). FNC_DATA should be passed as DATA to FNC. The
+ function for the file descriptor FD with direction dir (0: for writing,
+ 1: for reading). FNC_DATA should be passed as DATA to FNC. The
function should return a TAG suitable for the corresponding
- GpgmeRemoveIOCb. */
-typedef void *(*GpgmeRegisterIOCb) (void *data, int fd, int dir,
- GpgmeIOCb fnc, void *fnc_data);
+ GpgmeRemoveIOCb, and an error value. */
+typedef GpgmeError (*GpgmeRegisterIOCb) (void *data, int fd, int dir,
+ GpgmeIOCb fnc, void *fnc_data,
+ void **tag);
/* The type of a function that can remove a previously registered I/O
callback function given TAG as returned by the register
};
/* Set the I/O callback functions in CTX to IO_CBS. */
-void gpgme_set_op_io_cbs (GpgmeCtx ctx, struct GpgmeIOCbs *io_cbs);
+void gpgme_set_io_cbs (GpgmeCtx ctx, struct GpgmeIOCbs *io_cbs);
/* Get the current I/O callback functions. */
-void gpgme_get_op_io_cbs (GpgmeCtx ctx, struct GpgmeIOCbs *io_cbs);
+void gpgme_get_io_cbs (GpgmeCtx ctx, struct GpgmeIOCbs *io_cbs);
/* Cancel a pending operation in CTX. */
-void gpgme_cancel (GpgmeCtx ctx);
+void gpgme_cancel (GpgmeCtx ctx);
/* Process the pending operation and, if HANG is non-zero, wait for
the pending operation to finish. */
finish_key (GpgmeCtx ctx)
{
GpgmeKey key = ctx->tmp_key;
- struct key_queue_item_s *q, *q2;
+
+ ctx->tmp_key = NULL;
if (key)
+ _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_KEY, key);
+}
+
+
+void
+_gpgme_op_keylist_event_cb (void *data, GpgmeEventIO type, void *type_data)
+{
+ GpgmeCtx ctx = (GpgmeCtx) data;
+ GpgmeKey key = (GpgmeKey) type_data;
+ struct key_queue_item_s *q, *q2;
+
+ assert (type == GPGME_EVENT_NEXT_KEY);
+
+ _gpgme_key_cache_add (key);
+
+ q = xtrymalloc (sizeof *q);
+ if (!q)
{
- ctx->tmp_key = NULL;
-
- _gpgme_key_cache_add (key);
-
- q = xtrymalloc (sizeof *q);
- if (!q)
- {
- gpgme_key_release (key);
- ctx->error = mk_error (Out_Of_Core);
- return;
- }
- q->key = key;
- q->next = NULL;
- /* FIXME: Lock queue. Use a tail pointer? */
- if (!(q2 = ctx->key_queue))
- ctx->key_queue = q;
- else
- {
- for (; q2->next; q2 = q2->next)
- ;
- q2->next = q;
- }
- ctx->key_cond = 1;
- /* FIXME: Unlock queue. */
+ gpgme_key_release (key);
+ ctx->error = mk_error (Out_Of_Core);
+ return;
}
+ q->key = key;
+ q->next = NULL;
+ /* FIXME: Lock queue. Use a tail pointer? */
+ if (!(q2 = ctx->key_queue))
+ ctx->key_queue = q;
+ else
+ {
+ for (; q2->next; q2 = q2->next)
+ ;
+ q2->next = q;
+ }
+ ctx->key_cond = 1;
+ /* FIXME: Unlock queue. */
}
{
GpgmeError err = 0;
- /* Keylist operations are always "synchronous" in the sense that we
- don't add ourself to the global FD table. */
- err = _gpgme_op_reset (ctx, 1);
+ err = _gpgme_op_reset (ctx, 2);
if (err)
goto leave;
#include "context.h"
#include "ops.h"
+/* type is: 0: asynchronous operation (use global or user event loop).
+ 1: synchronous operation (always use private event loop).
+ 2: asynchronous private operation (use private or user
+ event loop). */
GpgmeError
-_gpgme_op_reset (GpgmeCtx ctx, int synchronous)
+_gpgme_op_reset (GpgmeCtx ctx, int type)
{
GpgmeError err = 0;
struct GpgmeIOCbs io_cbs;
if (err)
return err;
- if (synchronous)
+ if (type == 1 || (type == 2 && !ctx->io_cbs.add))
{
+ /* Use private event loop. */
io_cbs.add = _gpgme_add_io_cb;
io_cbs.add_priv = &ctx->fdt;
io_cbs.remove = _gpgme_remove_io_cb;
}
else if (! ctx->io_cbs.add)
{
+ /* Use global event loop. */
io_cbs.add = _gpgme_add_io_cb;
io_cbs.add_priv = NULL;
io_cbs.remove = _gpgme_remove_io_cb;
}
else
{
+ /* Use user event loop. */
io_cbs = ctx->io_cbs;
- io_cbs.event = _gpgme_op_event_cb;
+ /* We have to make sure that we notice the termination of the
+ operation ourself, so we stack another event handler on top
+ of the user-provided one. */
+ io_cbs.event = _gpgme_op_event_cb_user;
io_cbs.event_priv = ctx;
}
_gpgme_engine_set_io_cbs (ctx->engine, &io_cbs);
void _gpgme_set_op_info (GpgmeCtx c, GpgmeData info);
void _gpgme_op_event_cb (void *data, GpgmeEventIO type, void *type_data);
+void _gpgme_op_event_cb_user (void *data, GpgmeEventIO type, void *type_data);
/*-- wait.c --*/
GpgmeError _gpgme_wait_one (GpgmeCtx ctx);
/*-- keylist.c --*/
void _gpgme_release_keylist_result (KeylistResult res);
+void _gpgme_op_keylist_event_cb (void *data, GpgmeEventIO type, void *type_data);
+
+/*-- trustlist.c --*/
+void _gpgme_op_trustlist_event_cb (void *data, GpgmeEventIO type, void *type_data);
/*-- version.c --*/
const char *_gpgme_compare_versions (const char *my_version,
break;
}
}
- if (!not_done && gpg->io_cbs.event)
- (*gpg->io_cbs.event) (gpg->io_cbs.event_priv, GPGME_EVENT_DONE, NULL);
+ if (!not_done)
+ _gpgme_gpg_io_event (gpg, GPGME_EVENT_DONE, NULL);
}
const char *
_gpgme_gpg_add_io_cb (GpgObject gpg, int fd, int dir,
GpgmeIOCb handler, void *data, void **tag)
{
- GpgmeError err = 0;
+ GpgmeError err;
- *tag = (*gpg->io_cbs.add) (gpg->io_cbs.add_priv, fd, dir, handler, data);
- if (!tag)
- err = mk_error (General_Error);
- if (!err && !dir)
+ err = (*gpg->io_cbs.add) (gpg->io_cbs.add_priv, fd, dir, handler, data, tag);
+ if (err)
+ return err;
+ if (!dir)
/* FIXME Kludge around poll() problem. */
err = _gpgme_io_set_nonblocking (fd);
return err;
{
gpg->io_cbs = *io_cbs;
}
+
+
+void
+_gpgme_gpg_io_event (GpgObject gpg, GpgmeEventIO type, void *type_data)
+{
+ if (gpg->io_cbs.event)
+ (*gpg->io_cbs.event) (gpg->io_cbs.event_priv, type, type_data);
+}
GpgmeError _gpgme_gpg_op_verify (GpgObject gpg, GpgmeData sig, GpgmeData text);
GpgmeError _gpgme_gpg_spawn (GpgObject gpg, void *opaque);
void _gpgme_gpg_set_io_cbs (GpgObject gpg, struct GpgmeIOCbs *io_cbs);
+void _gpgme_gpg_io_event (GpgObject gpg, GpgmeEventIO type, void *type_data);
#endif /* RUNGPG_H */
char *p, *pend;
int field = 0;
GpgmeTrustItem item = NULL;
- struct trust_queue_item_s *q, *q2;
if (ctx->error)
return;
switch (field)
{
case 1: /* level */
- q = xtrymalloc (sizeof *q);
- if (!q)
- {
- ctx->error = mk_error (Out_Of_Core);
- return;
- }
- q->next = NULL;
- q->item = item = trust_item_new ();
- if (!q->item)
+ item = trust_item_new ();
+ if (!item)
{
- xfree (q);
ctx->error = mk_error (Out_Of_Core);
return;
}
- /* fixme: lock queue, keep a tail pointer */
- q2 = ctx->trust_queue;
- if (!q2)
- ctx->trust_queue = q;
- else
- {
- while (q2->next)
- q2 = q2->next;
- q2->next = q;
- }
- /* fixme: unlock queue */
item->level = atoi (p);
break;
case 2: /* long keyid */
}
}
- if (field)
- ctx->key_cond = 1;
+ if (item)
+ _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_TRUSTITEM, item);
+}
+
+
+void
+_gpgme_op_trustlist_event_cb (void *data, GpgmeEventIO type, void *type_data)
+{
+ GpgmeCtx ctx = (GpgmeCtx) data;
+ GpgmeTrustItem item = (GpgmeTrustItem) type_data;
+ struct trust_queue_item_s *q, *q2;
+
+ assert (type == GPGME_EVENT_NEXT_KEY);
+
+ q = xtrymalloc (sizeof *q);
+ if (!q)
+ {
+ gpgme_trust_item_release (item);
+ ctx->error = mk_error (Out_Of_Core);
+ return;
+ }
+ q->item = item;
+ q->next = NULL;
+ /* FIXME: lock queue, keep a tail pointer */
+ q2 = ctx->trust_queue;
+ if (!q2)
+ ctx->trust_queue = q;
+ else
+ {
+ while (q2->next)
+ q2 = q2->next;
+ q2->next = q;
+ }
+ /* FIXME: unlock queue */
+ ctx->key_cond = 1;
}
if (!pattern || !*pattern)
return mk_error (Invalid_Value);
- /* Trustlist operations are always "synchronous" in the sense that
- we don't add ourself to the global FD table. */
- err = _gpgme_op_reset (ctx, 1);
+ err = _gpgme_op_reset (ctx, 2);
if (err)
goto leave;
int idx;
};
-void *
+GpgmeError
_gpgme_add_io_cb (void *data, int fd, int dir,
- GpgmeIOCb fnc, void *fnc_data)
+ GpgmeIOCb fnc, void *fnc_data, void **r_tag)
{
GpgmeError err;
fd_table_t fdt = (fd_table_t) (data ? data : &fdt_global);
assert (fdt);
assert (fnc);
+ *r_tag = NULL;
tag = xtrymalloc (sizeof *tag);
if (!tag)
- return NULL;
+ return mk_error (Out_Of_Core);
tag->fdt = fdt;
/* Allocate a structure to hold info about the handler. */
if (!item)
{
xfree (tag);
- return NULL;
+ return mk_error (Out_Of_Core);
}
item->dir = dir;
item->handler = fnc;
{
xfree (tag);
xfree (item);
- errno = ENOMEM;
- return 0;
+ return mk_error (Out_Of_Core);
}
-
- return tag;
+
+ *r_tag = tag;
+ return 0;
}
void
void _gpgme_fd_table_init (fd_table_t fdt);
void _gpgme_fd_table_deinit (fd_table_t fdt);
-void *_gpgme_add_io_cb (void *data, int fd, int dir,
- GpgmeIOCb fnc, void *fnc_data);
+GpgmeError _gpgme_add_io_cb (void *data, int fd, int dir,
+ GpgmeIOCb fnc, void *fnc_data, void **r_tag);
void _gpgme_remove_io_cb (void *tag);
void _gpgme_wait_event_cb (void *data, GpgmeEventIO type, void *type_data);