2
Copyright (C) 2000 Werner Koch (dd9jn)
3
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 g10 Code GmbH
5
This file is part of GPGME.
7
GPGME is free software; you can redistribute it and/or modify it
8
under the terms of the GNU Lesser General Public License as
9
published by the Free Software Foundation; either version 2.1 of
10
the License, or (at your option) any later version.
12
GPGME is distributed in the hope that it will be useful, but
13
WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
Lesser General Public License for more details.
17
You should have received a copy of the GNU Lesser General Public
18
License along with this program; if not, write to the Free Software
19
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
29
#include <sys/types.h>
42
_gpgme_fd_table_init (fd_table_t fdt)
49
_gpgme_fd_table_deinit (fd_table_t fdt)
56
/* XXX We should keep a marker and roll over for speed. */
58
fd_table_put (fd_table_t fdt, int fd, int dir, void *opaque, int *idx)
61
struct io_select_fd_s *new_fds;
63
for (i = 0; i < fdt->size; i++)
65
if (fdt->fds[i].fd == -1)
70
#define FDT_ALLOCSIZE 10
71
new_fds = realloc (fdt->fds, (fdt->size + FDT_ALLOCSIZE)
74
return gpg_error_from_errno (errno);
77
fdt->size += FDT_ALLOCSIZE;
78
for (j = 0; j < FDT_ALLOCSIZE; j++)
79
fdt->fds[i + j].fd = -1;
83
fdt->fds[i].for_read = (dir == 1);
84
fdt->fds[i].for_write = (dir == 0);
85
fdt->fds[i].signaled = 0;
86
fdt->fds[i].opaque = opaque;
92
/* Register the file descriptor FD with the handler FNC (which gets
93
FNC_DATA as its first argument) for the direction DIR. DATA should
94
be the context for which the fd is added. R_TAG will hold the tag
95
that can be used to remove the fd. */
97
_gpgme_add_io_cb (void *data, int fd, int dir, gpgme_io_cb_t fnc,
98
void *fnc_data, void **r_tag)
101
gpgme_ctx_t ctx = (gpgme_ctx_t) data;
103
struct wait_item_s *item;
112
tag = malloc (sizeof *tag);
114
return gpg_error_from_errno (errno);
117
/* Allocate a structure to hold information about the handler. */
118
item = calloc (1, sizeof *item);
121
int saved_errno = errno;
123
return gpg_error_from_errno (saved_errno);
128
item->handler_value = fnc_data;
130
err = fd_table_put (fdt, fd, dir, item, &tag->idx);
138
TRACE3 (DEBUG_CTX, "_gpgme_add_io_cb", ctx,
139
"fd %d, dir=%d -> tag=%p", fd, dir, tag);
147
_gpgme_remove_io_cb (void *data)
149
struct tag *tag = data;
161
TRACE2 (DEBUG_CTX, "_gpgme_remove_io_cb", data,
162
"setting fd 0x%x (item=%p) done", fdt->fds[idx].fd,
163
fdt->fds[idx].opaque);
165
free (fdt->fds[idx].opaque);
168
/* Free the table entry. */
169
fdt->fds[idx].fd = -1;
170
fdt->fds[idx].for_read = 0;
171
fdt->fds[idx].for_write = 0;
172
fdt->fds[idx].opaque = NULL;
176
/* This is slightly embarrassing. The problem is that running an I/O
177
callback _may_ influence the status of other file descriptors. Our
178
own event loops could compensate for that, but the external event
179
loops cannot. FIXME: We may still want to optimize this a bit when
180
we are called from our own event loops. So if CHECKED is 1, the
183
_gpgme_run_io_cb (struct io_select_fd_s *an_fds, int checked)
185
struct wait_item_s *item;
186
item = (struct wait_item_s *) an_fds->opaque;
192
struct io_select_fd_s fds;
194
TRACE0 (DEBUG_CTX, "_gpgme_run_io_cb", item, "need to check");
197
/* Just give it a quick poll. */
198
nr = _gpgme_io_select (&fds, 1, 1);
203
/* The status changed in the meantime, there is nothing left
208
TRACE2 (DEBUG_CTX, "_gpgme_run_io_cb", item, "handler (%p, %d)",
209
item->handler_value, an_fds->fd);
210
return item->handler (item->handler_value, an_fds->fd);