2003-01-29 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
38 \f
39 void
40 _gpgme_fd_table_init (fd_table_t fdt)
41 {
42   fdt->fds = NULL;
43   fdt->size = 0;
44 }
45
46 void
47 _gpgme_fd_table_deinit (fd_table_t fdt)
48 {
49   if (fdt->fds)
50     free (fdt->fds);
51 }
52
53
54 /* XXX We should keep a marker and roll over for speed.  */
55 static GpgmeError
56 fd_table_put (fd_table_t fdt, int fd, int dir, void *opaque, int *idx)
57 {
58   int i, j;
59   struct io_select_fd_s *new_fds;
60
61   for (i = 0; i < fdt->size; i++)
62     {
63       if (fdt->fds[i].fd == -1)
64         break;
65     }
66   if (i == fdt->size)
67     {
68 #define FDT_ALLOCSIZE 10
69       new_fds = realloc (fdt->fds, (fdt->size + FDT_ALLOCSIZE)
70                          * sizeof (*new_fds));
71       if (!new_fds)
72         return GPGME_Out_Of_Core;
73       
74       fdt->fds = new_fds;
75       fdt->size += FDT_ALLOCSIZE;
76       for (j = 0; j < FDT_ALLOCSIZE; j++)
77         fdt->fds[i + j].fd = -1;
78     }
79
80   fdt->fds[i].fd = fd;
81   fdt->fds[i].for_read = (dir == 1);
82   fdt->fds[i].for_write = (dir == 0);
83   fdt->fds[i].frozen = 0;
84   fdt->fds[i].signaled = 0;
85   fdt->fds[i].opaque = opaque;
86   *idx = i;
87   return 0;
88 }
89
90 \f
91 /* Register the file descriptor FD with the handler FNC (which gets
92    FNC_DATA as its first argument) for the direction DIR.  DATA should
93    be the context for which the fd is added.  R_TAG will hold the tag
94    that can be used to remove the fd.  */
95 GpgmeError
96 _gpgme_add_io_cb (void *data, int fd, int dir, GpgmeIOCb fnc, void *fnc_data,
97                   void **r_tag)
98 {
99   GpgmeError err;
100   GpgmeCtx ctx = (GpgmeCtx) data;
101   fd_table_t fdt;
102   struct wait_item_s *item;
103   struct tag *tag;
104
105   assert (fnc);
106   assert (ctx);
107
108   fdt = &ctx->fdt;
109   assert (fdt);
110
111   tag = malloc (sizeof *tag);
112   if (!tag)
113     return GPGME_Out_Of_Core;
114   tag->ctx = ctx;
115
116   /* Allocate a structure to hold information about the handler.  */
117   item = calloc (1, sizeof *item);
118   if (!item)
119     {
120       free (tag);
121       return GPGME_Out_Of_Core;
122     }
123   item->ctx = ctx;
124   item->dir = dir;
125   item->handler = fnc;
126   item->handler_value = fnc_data;
127
128   err = fd_table_put (fdt, fd, dir, item, &tag->idx);
129   if (err)
130     {
131       free (tag);
132       free (item);
133       return err;
134     }
135
136   *r_tag = tag;
137   return 0;
138 }
139
140
141 void
142 _gpgme_remove_io_cb (void *data)
143 {
144   struct tag *tag = data;
145   GpgmeCtx ctx;
146   fd_table_t fdt;
147   int idx;
148
149   assert (tag);
150   ctx = tag->ctx;
151   assert (ctx);
152   fdt = &ctx->fdt;
153   assert (fdt);
154   idx = tag->idx;
155
156   DEBUG2 ("setting fd %d (item=%p) done", fdt->fds[idx].fd,
157           fdt->fds[idx].opaque);
158   free (fdt->fds[idx].opaque);
159   free (tag);
160
161   /* Free the table entry.  */
162   fdt->fds[idx].fd = -1;
163   fdt->fds[idx].for_read = 0;
164   fdt->fds[idx].for_write = 0;
165   fdt->fds[idx].opaque = NULL;
166 }