~ubuntu-branches/ubuntu/lucid/gpgme1.0/lucid

« back to all changes in this revision

Viewing changes to src/wait.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman, Bhavani Shankar, Scott Kitterman
  • Date: 2008-12-31 02:39:33 UTC
  • mfrom: (1.1.6 upstream) (3.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20081231023933-zi5r2w9vf7fdz0x9
Tags: 1.1.8-1ubuntu1
[ Bhavani Shankar ]
* Merge from debian unstable, remaining changes: LP: #311666
  - debian/rules: enable tests

[ Scott Kitterman ]
* Re-enable testsuite on armel since it's no longer a first build 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* wait.c 
 
2
   Copyright (C) 2000 Werner Koch (dd9jn)
 
3
   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 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 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.
 
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
   Lesser General Public License for more details.
 
16
   
 
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
 
20
   02111-1307, USA.  */
 
21
 
 
22
#if HAVE_CONFIG_H
 
23
#include <config.h>
 
24
#endif
 
25
#include <stdlib.h>
 
26
#include <string.h>
 
27
#include <assert.h>
 
28
#include <errno.h>
 
29
#include <sys/types.h>
 
30
 
 
31
#include "util.h"
 
32
#include "context.h"
 
33
#include "ops.h"
 
34
#include "wait.h"
 
35
#include "sema.h"
 
36
#include "priv-io.h"
 
37
#include "engine.h"
 
38
#include "debug.h"
 
39
 
 
40
 
 
41
void
 
42
_gpgme_fd_table_init (fd_table_t fdt)
 
43
{
 
44
  fdt->fds = NULL;
 
45
  fdt->size = 0;
 
46
}
 
47
 
 
48
void
 
49
_gpgme_fd_table_deinit (fd_table_t fdt)
 
50
{
 
51
  if (fdt->fds)
 
52
    free (fdt->fds);
 
53
}
 
54
 
 
55
 
 
56
/* XXX We should keep a marker and roll over for speed.  */
 
57
static gpgme_error_t
 
58
fd_table_put (fd_table_t fdt, int fd, int dir, void *opaque, int *idx)
 
59
{
 
60
  unsigned int i, j;
 
61
  struct io_select_fd_s *new_fds;
 
62
 
 
63
  for (i = 0; i < fdt->size; i++)
 
64
    {
 
65
      if (fdt->fds[i].fd == -1)
 
66
        break;
 
67
    }
 
68
  if (i == fdt->size)
 
69
    {
 
70
#define FDT_ALLOCSIZE 10
 
71
      new_fds = realloc (fdt->fds, (fdt->size + FDT_ALLOCSIZE)
 
72
                         * sizeof (*new_fds));
 
73
      if (!new_fds)
 
74
        return gpg_error_from_errno (errno);
 
75
      
 
76
      fdt->fds = new_fds;
 
77
      fdt->size += FDT_ALLOCSIZE;
 
78
      for (j = 0; j < FDT_ALLOCSIZE; j++)
 
79
        fdt->fds[i + j].fd = -1;
 
80
    }
 
81
 
 
82
  fdt->fds[i].fd = fd;
 
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;
 
87
  *idx = i;
 
88
  return 0;
 
89
}
 
90
 
 
91
 
 
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
gpgme_error_t
 
97
_gpgme_add_io_cb (void *data, int fd, int dir, gpgme_io_cb_t fnc,
 
98
                  void *fnc_data, void **r_tag)
 
99
{
 
100
  gpgme_error_t err;
 
101
  gpgme_ctx_t ctx = (gpgme_ctx_t) 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 gpg_error_from_errno (errno);
 
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
      int saved_errno = errno;
 
122
      free (tag);
 
123
      return gpg_error_from_errno (saved_errno);
 
124
    }
 
125
  item->ctx = ctx;
 
126
  item->dir = dir;
 
127
  item->handler = fnc;
 
128
  item->handler_value = fnc_data;
 
129
 
 
130
  err = fd_table_put (fdt, fd, dir, item, &tag->idx);
 
131
  if (err)
 
132
    {
 
133
      free (tag);
 
134
      free (item);
 
135
      return err;
 
136
    }
 
137
 
 
138
  TRACE3 (DEBUG_CTX, "_gpgme_add_io_cb", ctx,
 
139
          "fd %d, dir=%d -> tag=%p", fd, dir, tag);
 
140
 
 
141
  *r_tag = tag;
 
142
  return 0;
 
143
}
 
144
 
 
145
 
 
146
void
 
147
_gpgme_remove_io_cb (void *data)
 
148
{
 
149
  struct tag *tag = data;
 
150
  gpgme_ctx_t ctx;
 
151
  fd_table_t fdt;
 
152
  int idx;
 
153
 
 
154
  assert (tag);
 
155
  ctx = tag->ctx;
 
156
  assert (ctx);
 
157
  fdt = &ctx->fdt;
 
158
  assert (fdt);
 
159
  idx = tag->idx;
 
160
 
 
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);
 
164
 
 
165
  free (fdt->fds[idx].opaque);
 
166
  free (tag);
 
167
 
 
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;
 
173
}
 
174
 
 
175
 
 
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
 
181
   check is skipped.  */
 
182
gpgme_error_t
 
183
_gpgme_run_io_cb (struct io_select_fd_s *an_fds, int checked)
 
184
{
 
185
  struct wait_item_s *item;
 
186
  item = (struct wait_item_s *) an_fds->opaque;
 
187
  assert (item);
 
188
 
 
189
  if (!checked)
 
190
    {
 
191
      int nr;
 
192
      struct io_select_fd_s fds;
 
193
 
 
194
      TRACE0 (DEBUG_CTX, "_gpgme_run_io_cb", item, "need to check");
 
195
      fds = *an_fds;
 
196
      fds.signaled = 0;
 
197
      /* Just give it a quick poll.  */
 
198
      nr = _gpgme_io_select (&fds, 1, 1);
 
199
      assert (nr <= 1);
 
200
      if (nr < 0)
 
201
        return errno;
 
202
      else if (nr == 0)
 
203
        /* The status changed in the meantime, there is nothing left
 
204
           to do.  */
 
205
        return 0;
 
206
    }
 
207
 
 
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);
 
211
}