2003-02-04 Marcus Brinkmann <marcus@g10code.de>
[gpgme.git] / gpgme / wait.c
1 /* wait.c 
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002, 2003 g10 Code GmbH
4  
5    This file is part of GPGME.
6  
7    GPGME is free software; you can redistribute it and/or modify it
8    under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11  
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    General Public License for more details.
16  
17    You should have received a copy of the GNU General Public License
18    along with GPGME; if not, write to the Free Software Foundation,
19    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #if HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <stdlib.h>
25 #include <string.h>
26 #include <assert.h>
27 #include <errno.h>
28 #include <sys/types.h>
29
30 #include "util.h"
31 #include "context.h"
32 #include "ops.h"
33 #include "wait.h"
34 #include "sema.h"
35 #include "io.h"
36 #include "engine.h"
37 #include "debug.h"
38
39 \f
40 void
41 _gpgme_fd_table_init (fd_table_t fdt)
42 {
43   fdt->fds = NULL;
44   fdt->size = 0;
45 }
46
47 void
48 _gpgme_fd_table_deinit (fd_table_t fdt)
49 {
50   if (fdt->fds)
51     free (fdt->fds);
52 }
53
54
55 /* XXX We should keep a marker and roll over for speed.  */
56 static GpgmeError
57 fd_table_put (fd_table_t fdt, int fd, int dir, void *opaque, int *idx)
58 {
59   int i, j;
60   struct io_select_fd_s *new_fds;
61
62   for (i = 0; i < fdt->size; i++)
63     {
64       if (fdt->fds[i].fd == -1)
65         break;
66     }
67   if (i == fdt->size)
68     {
69 #define FDT_ALLOCSIZE 10
70       new_fds = realloc (fdt->fds, (fdt->size + FDT_ALLOCSIZE)
71                          * sizeof (*new_fds));
72       if (!new_fds)
73         return GPGME_Out_Of_Core;
74       
75       fdt->fds = new_fds;
76       fdt->size += FDT_ALLOCSIZE;
77       for (j = 0; j < FDT_ALLOCSIZE; j++)
78         fdt->fds[i + j].fd = -1;
79     }
80
81   fdt->fds[i].fd = fd;
82   fdt->fds[i].for_read = (dir == 1);
83   fdt->fds[i].for_write = (dir == 0);
84   fdt->fds[i].frozen = 0;
85   fdt->fds[i].signaled = 0;
86   fdt->fds[i].opaque = opaque;
87   *idx = i;
88   return 0;
89 }
90
91 \f
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.  */
96 GpgmeError
97 _gpgme_add_io_cb (void *data, int fd, int dir, GpgmeIOCb fnc, void *fnc_data,
98                   void **r_tag)
99 {
100   GpgmeError err;
101   GpgmeCtx ctx = (GpgmeCtx) data;
102   fd_table_t fdt;
103   struct wait_item_s *item;
104   struct tag *tag;
105
106   assert (fnc);
107   assert (ctx);
108
109   fdt = &ctx->fdt;
110   assert (fdt);
111
112   tag = malloc (sizeof *tag);
113   if (!tag)
114     return GPGME_Out_Of_Core;
115   tag->ctx = ctx;
116
117   /* Allocate a structure to hold information about the handler.  */
118   item = calloc (1, sizeof *item);
119   if (!item)
120     {
121       free (tag);
122       return GPGME_Out_Of_Core;
123     }
124   item->ctx = ctx;
125   item->dir = dir;
126   item->handler = fnc;
127   item->handler_value = fnc_data;
128
129   err = fd_table_put (fdt, fd, dir, item, &tag->idx);
130   if (err)
131     {
132       free (tag);
133       free (item);
134       return err;
135     }
136
137   *r_tag = tag;
138   return 0;
139 }
140
141
142 void
143 _gpgme_remove_io_cb (void *data)
144 {
145   struct tag *tag = data;
146   GpgmeCtx ctx;
147   fd_table_t fdt;
148   int idx;
149
150   assert (tag);
151   ctx = tag->ctx;
152   assert (ctx);
153   fdt = &ctx->fdt;
154   assert (fdt);
155   idx = tag->idx;
156
157   DEBUG2 ("setting fd %d (item=%p) done", fdt->fds[idx].fd,
158           fdt->fds[idx].opaque);
159   free (fdt->fds[idx].opaque);
160   free (tag);
161
162   /* Free the table entry.  */
163   fdt->fds[idx].fd = -1;
164   fdt->fds[idx].for_read = 0;
165   fdt->fds[idx].for_write = 0;
166   fdt->fds[idx].opaque = NULL;
167 }