aboutsummaryrefslogtreecommitdiffstats
path: root/gpgme/wait.c
diff options
context:
space:
mode:
Diffstat (limited to 'gpgme/wait.c')
-rw-r--r--gpgme/wait.c324
1 files changed, 52 insertions, 272 deletions
diff --git a/gpgme/wait.c b/gpgme/wait.c
index 4570913f..daf009b8 100644
--- a/gpgme/wait.c
+++ b/gpgme/wait.c
@@ -1,26 +1,26 @@
/* wait.c
- * Copyright (C) 2000 Werner Koch (dd9jn)
- * Copyright (C) 2001, 2002 g10 Code GmbH
- *
- * This file is part of GPGME.
- *
- * GPGME is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GPGME is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003 g10 Code GmbH
+
+ This file is part of GPGME.
+
+ GPGME is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ GPGME is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GPGME; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+#if HAVE_CONFIG_H
#include <config.h>
-#include <stdio.h>
+#endif
#include <stdlib.h>
#include <string.h>
#include <assert.h>
@@ -35,28 +35,10 @@
#include "io.h"
#include "engine.h"
-static struct fd_table fdt_global;
-
-static GpgmeCtx *ctx_done_list;
-static int ctx_done_list_size;
-static int ctx_done_list_length;
-DEFINE_STATIC_LOCK (ctx_done_list_lock);
-
-static GpgmeIdleFunc idle_function;
-
-struct wait_item_s
-{
- struct wait_item_s *next;
- GpgmeIOCb handler;
- void *handler_value;
- int dir;
-};
-
void
_gpgme_fd_table_init (fd_table_t fdt)
{
- INIT_LOCK (fdt->lock);
fdt->fds = NULL;
fdt->size = 0;
}
@@ -64,19 +46,18 @@ _gpgme_fd_table_init (fd_table_t fdt)
void
_gpgme_fd_table_deinit (fd_table_t fdt)
{
- DESTROY_LOCK (fdt->lock);
if (fdt->fds)
free (fdt->fds);
}
+
/* XXX We should keep a marker and roll over for speed. */
-GpgmeError
-_gpgme_fd_table_put (fd_table_t fdt, int fd, int dir, void *opaque, int *idx)
+static GpgmeError
+fd_table_put (fd_table_t fdt, int fd, int dir, void *opaque, int *idx)
{
int i, j;
struct io_select_fd_s *new_fds;
- LOCK (fdt->lock);
for (i = 0; i < fdt->size; i++)
{
if (fdt->fds[i].fd == -1)
@@ -88,10 +69,7 @@ _gpgme_fd_table_put (fd_table_t fdt, int fd, int dir, void *opaque, int *idx)
new_fds = realloc (fdt->fds, (fdt->size + FDT_ALLOCSIZE)
* sizeof (*new_fds));
if (!new_fds)
- {
- UNLOCK (fdt->lock);
- return mk_error (Out_Of_Core);
- }
+ return mk_error (Out_Of_Core);
fdt->fds = new_fds;
fdt->size += FDT_ALLOCSIZE;
@@ -105,272 +83,76 @@ _gpgme_fd_table_put (fd_table_t fdt, int fd, int dir, void *opaque, int *idx)
fdt->fds[i].frozen = 0;
fdt->fds[i].signaled = 0;
fdt->fds[i].opaque = opaque;
- UNLOCK (fdt->lock);
*idx = i;
return 0;
}
-/**
- * gpgme_register_idle:
- * @fnc: Callers idle function
- *
- * Register a function with GPGME called by GPGME whenever it feels
- * that is is idle. NULL may be used to remove this function.
- *
- * Return value: The idle function pointer that was passed to the
- * function at the last time it was invoked, or NULL if the function
- * is invoked the first time.
- **/
-GpgmeIdleFunc
-gpgme_register_idle (GpgmeIdleFunc idle)
-{
- GpgmeIdleFunc old_idle = idle_function;
-
- idle_function = idle;
- return old_idle;
-}
-
-
-/* Wait on all file descriptors listed in FDT and process them using
- the registered callbacks. Returns -1 on error (with errno set), 0
- if nothing to run and 1 if it did run something. */
-static int
-do_select (fd_table_t fdt)
-{
- int i, n;
- int any = 0;
-
- LOCK (fdt->lock);
- n = _gpgme_io_select (fdt->fds, fdt->size, 0);
-
- if (n <= 0)
- {
- UNLOCK (fdt->lock);
- return n; /* Error or timeout. */
- }
-
- for (i = 0; i < fdt->size && n; i++)
- {
- if (fdt->fds[i].fd != -1 && fdt->fds[i].signaled)
- {
- struct wait_item_s *item;
-
- assert (n);
- n--;
-
- item = (struct wait_item_s *) fdt->fds[i].opaque;
- assert (item);
- any = 1;
-
- fdt->fds[i].signaled = 0;
- UNLOCK (fdt->lock);
- item->handler (item->handler_value, fdt->fds[i].fd);
- LOCK (fdt->lock);
- }
- }
- UNLOCK (fdt->lock);
-
- return any;
-}
-
-
-
-void
-_gpgme_wait_event_cb (void *data, GpgmeEventIO type, void *type_data)
-{
- if (type != GPGME_EVENT_DONE)
- return;
-
- if (ctx_done_list_size == ctx_done_list_length)
- {
-#define CTX_DONE_LIST_SIZE_INITIAL 8
- int new_size = ctx_done_list_size ? 2 * ctx_done_list_size
- : CTX_DONE_LIST_SIZE_INITIAL;
- GpgmeCtx *new_list = realloc (ctx_done_list,
- new_size * sizeof (GpgmeCtx *));
- assert (new_list);
-#if 0
- if (!new_list)
- return mk_error (Out_Of_Core);
-#endif
- ctx_done_list = new_list;
- ctx_done_list_size = new_size;
- }
- ctx_done_list[ctx_done_list_length++] = (GpgmeCtx) data;
-}
-
-
-/**
- * gpgme_wait:
- * @c:
- * @hang:
- *
- * Wait for a finished request, if @c is given the function does only
- * wait on a finished request for that context, otherwise it will return
- * on any request. When @hang is true the function will wait, otherwise
- * it will return immediately when there is no pending finished request.
- *
- * Return value: Context of the finished request or NULL if @hang is false
- * and no (or not the given) request has finished.
- **/
-GpgmeCtx
-gpgme_wait (GpgmeCtx ctx, GpgmeError *status, int hang)
-{
- DEBUG2 ("waiting... ctx=%p hang=%d", ctx, hang);
- do
- {
- int i;
-
- /* XXX We are ignoring all errors from select here. */
- do_select (&fdt_global);
-
- LOCK (ctx_done_list_lock);
- /* A process that is done is eligible for election if it is the
- requested context or if it was not yet reported. */
- for (i = 0; i < ctx_done_list_length; i++)
- if (!ctx || ctx == ctx_done_list[i])
- break;
- if (i < ctx_done_list_length)
- {
- if (!ctx)
- ctx = ctx_done_list[i];
- hang = 0;
- ctx->pending = 0;
- if (--ctx_done_list_length)
- memcpy (&ctx_done_list[i],
- &ctx_done_list[i + 1],
- (ctx_done_list_length - i) * sizeof (GpgmeCtx *));
- }
- UNLOCK (ctx_done_list_lock);
-
- if (hang && idle_function)
- idle_function ();
- }
- while (hang && (!ctx || !ctx->cancel));
-
- if (ctx && ctx->cancel)
- {
- /* FIXME: Paranoia? */
- ctx->cancel = 0;
- ctx->pending = 0;
- ctx->error = mk_error (Canceled);
- }
-
- if (ctx && status)
- *status = ctx->error;
- return ctx;
-}
-
-
-GpgmeError
-_gpgme_wait_one (GpgmeCtx ctx)
-{
- return _gpgme_wait_on_condition (ctx, NULL);
-}
-
-
-GpgmeError
-_gpgme_wait_on_condition (GpgmeCtx ctx, volatile int *cond)
-{
- GpgmeError err = 0;
- int hang = 1;
- DEBUG1 ("waiting... ctx=%p", ctx);
- do
- {
- if (do_select (&ctx->fdt) < 0)
- {
- err = mk_error (File_Error);
- hang = 0;
- }
- else if (cond && *cond)
- hang = 0;
- else
- {
- int any = 0;
- int i;
-
- LOCK (ctx->fdt.lock);
- for (i = 0; i < ctx->fdt.size; i++)
- {
- if (ctx->fdt.fds[i].fd != -1)
- {
- any = 1;
- break;
- }
- }
- if (!any)
- hang = 0;
- UNLOCK (ctx->fdt.lock);
- }
- }
- while (hang && !ctx->cancel);
- if (!err && ctx->cancel)
- {
- /* FIXME: Paranoia? */
- ctx->cancel = 0;
- ctx->pending = 0;
- ctx->error = mk_error (Canceled);
- }
- return err ? err : ctx->error;
-}
-
-
-struct tag
-{
- fd_table_t fdt;
- int idx;
-};
-
+/* Register the file descriptor FD with the handler FNC (which gets
+ FNC_DATA as its first argument) for the direction DIR. DATA should
+ be the context for which the fd is added. R_TAG will hold the tag
+ that can be used to remove the fd. */
GpgmeError
-_gpgme_add_io_cb (void *data, int fd, int dir,
- GpgmeIOCb fnc, void *fnc_data, void **r_tag)
+_gpgme_add_io_cb (void *data, int fd, int dir, GpgmeIOCb fnc, void *fnc_data,
+ void **r_tag)
{
GpgmeError err;
- fd_table_t fdt = (fd_table_t) (data ? data : &fdt_global);
+ GpgmeCtx ctx = (GpgmeCtx) data;
+ fd_table_t fdt;
struct wait_item_s *item;
struct tag *tag;
- assert (fdt);
assert (fnc);
+ assert (ctx);
+
+ fdt = &ctx->fdt;
+ assert (fdt);
- *r_tag = NULL;
tag = malloc (sizeof *tag);
if (!tag)
return mk_error (Out_Of_Core);
- tag->fdt = fdt;
+ tag->ctx = ctx;
- /* Allocate a structure to hold info about the handler. */
+ /* Allocate a structure to hold information about the handler. */
item = calloc (1, sizeof *item);
if (!item)
{
free (tag);
return mk_error (Out_Of_Core);
}
+ item->ctx = ctx;
item->dir = dir;
item->handler = fnc;
item->handler_value = fnc_data;
- err = _gpgme_fd_table_put (fdt, fd, dir, item, &tag->idx);
+ err = fd_table_put (fdt, fd, dir, item, &tag->idx);
if (err)
{
free (tag);
free (item);
- return mk_error (Out_Of_Core);
+ return err;
}
*r_tag = tag;
return 0;
}
+
void
_gpgme_remove_io_cb (void *data)
{
struct tag *tag = data;
- fd_table_t fdt = tag->fdt;
- int idx = tag->idx;
+ GpgmeCtx ctx;
+ fd_table_t fdt;
+ int idx;
+
+ assert (tag);
+ ctx = tag->ctx;
+ assert (ctx);
+ fdt = &ctx->fdt;
+ assert (fdt);
+ idx = tag->idx;
- LOCK (fdt->lock);
DEBUG2 ("setting fd %d (item=%p) done", fdt->fds[idx].fd,
fdt->fds[idx].opaque);
free (fdt->fds[idx].opaque);
@@ -381,6 +163,4 @@ _gpgme_remove_io_cb (void *data)
fdt->fds[idx].for_read = 0;
fdt->fds[idx].for_write = 0;
fdt->fds[idx].opaque = NULL;
- UNLOCK (fdt->lock);
}
-