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.
This commit is contained in:
Marcus Brinkmann 2002-07-03 01:57:03 +00:00
parent 0cf2a8a51a
commit b92c8f057c
15 changed files with 242 additions and 95 deletions

View File

@ -1,3 +1,41 @@
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> 2002-06-28 Marcus Brinkmann <marcus@g10code.de>
* keylist.c (gpgme_op_keylist_ext_start): Always use our own FD * keylist.c (gpgme_op_keylist_ext_start): Always use our own FD

View File

@ -1290,14 +1290,14 @@ static GpgmeError
_gpgme_gpgsm_add_io_cb (GpgsmObject gpgsm, iocb_data_t *iocbd, _gpgme_gpgsm_add_io_cb (GpgsmObject gpgsm, iocb_data_t *iocbd,
GpgmeIOCb handler) GpgmeIOCb handler)
{ {
GpgmeError err = 0; GpgmeError err;
iocbd->tag = (*gpgsm->io_cbs.add) (gpgsm->io_cbs.add_priv, err = (*gpgsm->io_cbs.add) (gpgsm->io_cbs.add_priv,
iocbd->fd, iocbd->dir, iocbd->fd, iocbd->dir,
handler, iocbd->data); handler, iocbd->data, &iocbd->tag);
if (!iocbd->tag) if (err)
err = mk_error (General_Error); return err;
if (!err && !iocbd->dir) if (!iocbd->dir)
/* FIXME Kludge around poll() problem. */ /* FIXME Kludge around poll() problem. */
err = _gpgme_io_set_nonblocking (iocbd->fd); err = _gpgme_io_set_nonblocking (iocbd->fd);
return err; return err;
@ -1338,6 +1338,12 @@ _gpgme_gpgsm_set_io_cbs (GpgsmObject gpgsm, struct GpgmeIOCbs *io_cbs)
gpgsm->io_cbs = *io_cbs; 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 */ #else /* ENABLE_GPGSM */
@ -1486,4 +1492,9 @@ _gpgme_gpgsm_set_io_cbs (GpgsmObject gpgsm, struct GpgmeIOCbs *io_cbs)
{ {
} }
void
_gpgme_gpgsm_io_event (GpgsmObject gpgsm, GpgmeEventIO type, void *type_data)
{
}
#endif /* ! ENABLE_GPGSM */ #endif /* ! ENABLE_GPGSM */

View File

@ -64,5 +64,6 @@ GpgmeError _gpgme_gpgsm_op_verify (GpgsmObject gpgsm, GpgmeData sig,
GpgmeData text); GpgmeData text);
GpgmeError _gpgme_gpgsm_start (GpgsmObject gpgsm, void *opaque); GpgmeError _gpgme_gpgsm_start (GpgsmObject gpgsm, void *opaque);
void _gpgme_gpgsm_set_io_cbs (GpgsmObject gpgsm, struct GpgmeIOCbs *io_cbs); 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 */ #endif /* ENGINE_GPGSM_H */

View File

@ -587,6 +587,26 @@ _gpgme_engine_set_io_cbs (EngineObject engine,
} }
} }
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;
}
}
void void
_gpgme_engine_add_child_to_reap_list (void *buf, int buflen, pid_t pid) _gpgme_engine_add_child_to_reap_list (void *buf, int buflen, pid_t pid)

View File

@ -78,6 +78,8 @@ GpgmeError _gpgme_engine_start (EngineObject engine, void *opaque);
void _gpgme_engine_set_io_cbs (EngineObject engine, void _gpgme_engine_set_io_cbs (EngineObject engine,
struct GpgmeIOCbs *io_cbs); 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_add_child_to_reap_list (void *buf, int buflen, pid_t pid);
void _gpgme_engine_housecleaning (void); void _gpgme_engine_housecleaning (void);

View File

@ -507,7 +507,10 @@ gpgme_get_progress_cb (GpgmeCtx ctx, GpgmeProgressCb *r_cb, void **r_cb_value)
void void
gpgme_set_io_cbs (GpgmeCtx ctx, struct GpgmeIOCbs *io_cbs) 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; ctx->io_cbs = *io_cbs;
else else
{ {
@ -544,9 +547,36 @@ _gpgme_op_event_cb (void *data, GpgmeEventIO type, void *type_data)
{ {
GpgmeCtx ctx = data; GpgmeCtx ctx = data;
if (type == GPGME_EVENT_DONE) switch (type)
{
case GPGME_EVENT_DONE:
ctx->pending = 0; ctx->pending = 0;
break;
if (ctx->io_cbs.add && ctx->io_cbs.event) case GPGME_EVENT_NEXT_KEY:
_gpgme_op_keylist_event_cb (data, type, type_data);
break;
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); (*ctx->io_cbs.event) (ctx->io_cbs.event_priv, type, type_data);
} }
}

View File

@ -339,12 +339,13 @@ char *gpgme_get_op_info (GpgmeCtx ctx, int reserved);
typedef void (*GpgmeIOCb) (void *data, int fd); typedef void (*GpgmeIOCb) (void *data, int fd);
/* The type of a function that can register FNC as the I/O callback /* 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, function for the file descriptor FD with direction dir (0: for writing,
1: outbound). FNC_DATA should be passed as DATA to FNC. The 1: for reading). FNC_DATA should be passed as DATA to FNC. The
function should return a TAG suitable for the corresponding function should return a TAG suitable for the corresponding
GpgmeRemoveIOCb. */ GpgmeRemoveIOCb, and an error value. */
typedef void *(*GpgmeRegisterIOCb) (void *data, int fd, int dir, typedef GpgmeError (*GpgmeRegisterIOCb) (void *data, int fd, int dir,
GpgmeIOCb fnc, void *fnc_data); GpgmeIOCb fnc, void *fnc_data,
void **tag);
/* The type of a function that can remove a previously registered I/O /* The type of a function that can remove a previously registered I/O
callback function given TAG as returned by the register callback function given TAG as returned by the register
@ -370,10 +371,10 @@ struct GpgmeIOCbs
}; };
/* Set the I/O callback functions in CTX to IO_CBS. */ /* 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. */ /* 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. */ /* Cancel a pending operation in CTX. */
void gpgme_cancel (GpgmeCtx ctx); void gpgme_cancel (GpgmeCtx ctx);

View File

@ -514,11 +514,22 @@ static void
finish_key (GpgmeCtx ctx) finish_key (GpgmeCtx ctx)
{ {
GpgmeKey key = ctx->tmp_key; GpgmeKey key = ctx->tmp_key;
struct key_queue_item_s *q, *q2;
ctx->tmp_key = NULL;
if (key) 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)
{ {
ctx->tmp_key = NULL; 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); _gpgme_key_cache_add (key);
@ -543,7 +554,6 @@ finish_key (GpgmeCtx ctx)
ctx->key_cond = 1; ctx->key_cond = 1;
/* FIXME: Unlock queue. */ /* FIXME: Unlock queue. */
} }
}
/** /**
@ -563,9 +573,7 @@ gpgme_op_keylist_start (GpgmeCtx ctx, const char *pattern, int secret_only)
{ {
GpgmeError err = 0; GpgmeError err = 0;
/* Keylist operations are always "synchronous" in the sense that we err = _gpgme_op_reset (ctx, 2);
don't add ourself to the global FD table. */
err = _gpgme_op_reset (ctx, 1);
if (err) if (err)
goto leave; goto leave;

View File

@ -24,8 +24,12 @@
#include "context.h" #include "context.h"
#include "ops.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 GpgmeError
_gpgme_op_reset (GpgmeCtx ctx, int synchronous) _gpgme_op_reset (GpgmeCtx ctx, int type)
{ {
GpgmeError err = 0; GpgmeError err = 0;
struct GpgmeIOCbs io_cbs; struct GpgmeIOCbs io_cbs;
@ -43,8 +47,9 @@ _gpgme_op_reset (GpgmeCtx ctx, int synchronous)
if (err) if (err)
return 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 = _gpgme_add_io_cb;
io_cbs.add_priv = &ctx->fdt; io_cbs.add_priv = &ctx->fdt;
io_cbs.remove = _gpgme_remove_io_cb; io_cbs.remove = _gpgme_remove_io_cb;
@ -53,6 +58,7 @@ _gpgme_op_reset (GpgmeCtx ctx, int synchronous)
} }
else if (! ctx->io_cbs.add) else if (! ctx->io_cbs.add)
{ {
/* Use global event loop. */
io_cbs.add = _gpgme_add_io_cb; io_cbs.add = _gpgme_add_io_cb;
io_cbs.add_priv = NULL; io_cbs.add_priv = NULL;
io_cbs.remove = _gpgme_remove_io_cb; io_cbs.remove = _gpgme_remove_io_cb;
@ -61,8 +67,12 @@ _gpgme_op_reset (GpgmeCtx ctx, int synchronous)
} }
else else
{ {
/* Use user event loop. */
io_cbs = ctx->io_cbs; 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; io_cbs.event_priv = ctx;
} }
_gpgme_engine_set_io_cbs (ctx->engine, &io_cbs); _gpgme_engine_set_io_cbs (ctx->engine, &io_cbs);

View File

@ -47,6 +47,7 @@ void _gpgme_release_result ( GpgmeCtx c );
void _gpgme_set_op_info (GpgmeCtx c, GpgmeData info); 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 (void *data, GpgmeEventIO type, void *type_data);
void _gpgme_op_event_cb_user (void *data, GpgmeEventIO type, void *type_data);
/*-- wait.c --*/ /*-- wait.c --*/
GpgmeError _gpgme_wait_one (GpgmeCtx ctx); GpgmeError _gpgme_wait_one (GpgmeCtx ctx);
@ -131,6 +132,10 @@ void _gpgme_release_genkey_result (GenKeyResult res);
/*-- keylist.c --*/ /*-- keylist.c --*/
void _gpgme_release_keylist_result (KeylistResult res); 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 --*/ /*-- version.c --*/
const char *_gpgme_compare_versions (const char *my_version, const char *_gpgme_compare_versions (const char *my_version,

View File

@ -212,8 +212,8 @@ close_notify_handler (int fd, void *opaque)
break; break;
} }
} }
if (!not_done && gpg->io_cbs.event) if (!not_done)
(*gpg->io_cbs.event) (gpg->io_cbs.event_priv, GPGME_EVENT_DONE, NULL); _gpgme_gpg_io_event (gpg, GPGME_EVENT_DONE, NULL);
} }
const char * const char *
@ -807,12 +807,12 @@ static GpgmeError
_gpgme_gpg_add_io_cb (GpgObject gpg, int fd, int dir, _gpgme_gpg_add_io_cb (GpgObject gpg, int fd, int dir,
GpgmeIOCb handler, void *data, void **tag) 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); err = (*gpg->io_cbs.add) (gpg->io_cbs.add_priv, fd, dir, handler, data, tag);
if (!tag) if (err)
err = mk_error (General_Error); return err;
if (!err && !dir) if (!dir)
/* FIXME Kludge around poll() problem. */ /* FIXME Kludge around poll() problem. */
err = _gpgme_io_set_nonblocking (fd); err = _gpgme_io_set_nonblocking (fd);
return err; return err;
@ -1749,3 +1749,11 @@ _gpgme_gpg_set_io_cbs (GpgObject gpg, struct GpgmeIOCbs *io_cbs)
{ {
gpg->io_cbs = *io_cbs; 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);
}

View File

@ -162,5 +162,6 @@ GpgmeError _gpgme_gpg_op_trustlist (GpgObject gpg, const char *pattern);
GpgmeError _gpgme_gpg_op_verify (GpgObject gpg, GpgmeData sig, GpgmeData text); GpgmeError _gpgme_gpg_op_verify (GpgObject gpg, GpgmeData sig, GpgmeData text);
GpgmeError _gpgme_gpg_spawn (GpgObject gpg, void *opaque); GpgmeError _gpgme_gpg_spawn (GpgObject gpg, void *opaque);
void _gpgme_gpg_set_io_cbs (GpgObject gpg, struct GpgmeIOCbs *io_cbs); 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 */ #endif /* RUNGPG_H */

View File

@ -87,7 +87,6 @@ trustlist_colon_handler (GpgmeCtx ctx, char *line)
char *p, *pend; char *p, *pend;
int field = 0; int field = 0;
GpgmeTrustItem item = NULL; GpgmeTrustItem item = NULL;
struct trust_queue_item_s *q, *q2;
if (ctx->error) if (ctx->error)
return; return;
@ -104,31 +103,12 @@ trustlist_colon_handler (GpgmeCtx ctx, char *line)
switch (field) switch (field)
{ {
case 1: /* level */ case 1: /* level */
q = xtrymalloc (sizeof *q); item = trust_item_new ();
if (!q) if (!item)
{ {
ctx->error = mk_error (Out_Of_Core); ctx->error = mk_error (Out_Of_Core);
return; return;
} }
q->next = NULL;
q->item = item = trust_item_new ();
if (!q->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); item->level = atoi (p);
break; break;
case 2: /* long keyid */ case 2: /* long keyid */
@ -154,7 +134,40 @@ trustlist_colon_handler (GpgmeCtx ctx, char *line)
} }
} }
if (field) 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; ctx->key_cond = 1;
} }
@ -167,9 +180,7 @@ gpgme_op_trustlist_start (GpgmeCtx ctx, const char *pattern, int max_level)
if (!pattern || !*pattern) if (!pattern || !*pattern)
return mk_error (Invalid_Value); return mk_error (Invalid_Value);
/* Trustlist operations are always "synchronous" in the sense that err = _gpgme_op_reset (ctx, 2);
we don't add ourself to the global FD table. */
err = _gpgme_op_reset (ctx, 1);
if (err) if (err)
goto leave; goto leave;

View File

@ -332,9 +332,9 @@ struct tag
int idx; int idx;
}; };
void * GpgmeError
_gpgme_add_io_cb (void *data, int fd, int dir, _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; GpgmeError err;
fd_table_t fdt = (fd_table_t) (data ? data : &fdt_global); fd_table_t fdt = (fd_table_t) (data ? data : &fdt_global);
@ -344,9 +344,10 @@ _gpgme_add_io_cb (void *data, int fd, int dir,
assert (fdt); assert (fdt);
assert (fnc); assert (fnc);
*r_tag = NULL;
tag = xtrymalloc (sizeof *tag); tag = xtrymalloc (sizeof *tag);
if (!tag) if (!tag)
return NULL; return mk_error (Out_Of_Core);
tag->fdt = fdt; tag->fdt = fdt;
/* Allocate a structure to hold info about the handler. */ /* Allocate a structure to hold info about the handler. */
@ -354,7 +355,7 @@ _gpgme_add_io_cb (void *data, int fd, int dir,
if (!item) if (!item)
{ {
xfree (tag); xfree (tag);
return NULL; return mk_error (Out_Of_Core);
} }
item->dir = dir; item->dir = dir;
item->handler = fnc; item->handler = fnc;
@ -365,11 +366,11 @@ _gpgme_add_io_cb (void *data, int fd, int dir,
{ {
xfree (tag); xfree (tag);
xfree (item); xfree (item);
errno = ENOMEM; return mk_error (Out_Of_Core);
return 0;
} }
return tag; *r_tag = tag;
return 0;
} }
void void

View File

@ -36,8 +36,8 @@ typedef struct fd_table *fd_table_t;
void _gpgme_fd_table_init (fd_table_t fdt); void _gpgme_fd_table_init (fd_table_t fdt);
void _gpgme_fd_table_deinit (fd_table_t fdt); void _gpgme_fd_table_deinit (fd_table_t fdt);
void *_gpgme_add_io_cb (void *data, int fd, int dir, GpgmeError _gpgme_add_io_cb (void *data, int fd, int dir,
GpgmeIOCb fnc, void *fnc_data); GpgmeIOCb fnc, void *fnc_data, void **r_tag);
void _gpgme_remove_io_cb (void *tag); void _gpgme_remove_io_cb (void *tag);
void _gpgme_wait_event_cb (void *data, GpgmeEventIO type, void *type_data); void _gpgme_wait_event_cb (void *data, GpgmeEventIO type, void *type_data);