Fix comment indentation.
[gpgme.git] / gpgme / wait-private.c
1 /* wait-private.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 <assert.h>
25
26 #include "gpgme.h"
27 #include "context.h"
28 #include "wait.h"
29 #include "ops.h"
30 #include "io.h"
31 #include "util.h"
32
33 \f
34 /* The private event loops are used for all blocking operations, and
35    for the key and trust item listing operations.  They are completely
36    separated from each other.  */
37
38 \f
39 /* Internal I/O callback functions.  */
40
41 /* The add_io_cb and remove_io_cb handlers are shared with the global
42    event loops.  */
43
44 void
45 _gpgme_wait_private_event_cb (void *data, GpgmeEventIO type, void *type_data)
46 {
47   GpgmeCtx ctx = data;
48
49   switch (type)
50     {
51     case GPGME_EVENT_START:
52       /* Nothing to do here, as the wait routine is called after the
53          initialization is finished.  */
54       break;
55
56     case GPGME_EVENT_DONE:
57       ctx->pending = 0;
58       break;
59
60     case GPGME_EVENT_NEXT_KEY:
61       _gpgme_op_keylist_event_cb (data, type, type_data);
62       break;
63
64     case GPGME_EVENT_NEXT_TRUSTITEM:
65       _gpgme_op_trustlist_event_cb (data, type, type_data);
66       break;
67     }
68 }
69
70 \f
71 /* If COND is a null pointer, wait until the blocking operation in CTX
72    finished and return its error value.  Otherwise, wait until COND is
73    satisfied or the operation finished.  */
74 GpgmeError
75 _gpgme_wait_on_condition (GpgmeCtx ctx, volatile int *cond)
76 {
77   GpgmeError err = 0;
78   int hang = 1;
79
80   do
81     {
82       int nr = _gpgme_io_select (ctx->fdt.fds, ctx->fdt.size, 0);
83       int i;
84
85       if (nr < 0)
86         {
87           /* An error occured.  Close all fds in this context, and
88              signal it.  */
89           int idx;
90
91           err = GPGME_File_Error;
92           for (idx = 0; idx < ctx->fdt.size; idx++)
93             if (ctx->fdt.fds[idx].fd != -1)
94               _gpgme_io_close (ctx->fdt.fds[idx].fd);
95           _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err);
96
97           return err;
98         }
99       
100       for (i = 0; i < ctx->fdt.size && nr; i++)
101         {
102           if (ctx->fdt.fds[i].fd != -1 && ctx->fdt.fds[i].signaled)
103             {
104               struct wait_item_s *item;
105               
106               ctx->fdt.fds[i].signaled = 0;
107               assert (nr);
108               nr--;
109               
110               item = (struct wait_item_s *) ctx->fdt.fds[i].opaque;
111
112               err = item->handler (item->handler_value, ctx->fdt.fds[i].fd);
113               if (!err && ctx->cancel)
114                 err = GPGME_Canceled;
115               if (err)
116                 {
117                   /* An error occured.  Close all fds in this context,
118                      and signal it.  */
119                   int idx;
120                   
121                   for (idx = 0; idx < ctx->fdt.size; idx++)
122                     if (ctx->fdt.fds[idx].fd != -1)
123                       _gpgme_io_close (ctx->fdt.fds[idx].fd);
124                   _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err);
125                   return err;
126                 }
127             }
128         }
129
130       for (i = 0; i < ctx->fdt.size; i++)
131         if (ctx->fdt.fds[i].fd != -1)
132           break;
133       if (i == ctx->fdt.size)
134         {
135           _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err);
136           hang = 0;
137         }
138       if (cond && *cond)
139         hang = 0;
140     }
141   while (hang);
142
143   return 0;
144 }
145
146
147 /* Wait until the blocking operation in context CTX has finished and
148    return the error value.  */
149 GpgmeError
150 _gpgme_wait_one (GpgmeCtx ctx)
151 {
152   return _gpgme_wait_on_condition (ctx, NULL);
153 }