2003-05-18 Marcus Brinkmann <marcus@g10code.de>
[gpgme.git] / tests / gpg / t-eventloop.c
1 /* t-eventloop.c  - regression test
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 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <assert.h>
25 #include <errno.h>
26 #include <sys/select.h>
27
28 #include <gpgme.h>
29
30 #define fail_if_err(a) do { if(a) {                                       \
31                                fprintf (stderr, "%s:%d: gpgme_error_t %s\n", \
32                                 __FILE__, __LINE__, gpgme_strerror(a));   \
33                                 exit (1); }                               \
34                              } while(0)
35
36 static void
37 print_data (gpgme_data_t dh)
38 {
39   char buf[100];
40   int ret;
41   
42   ret = gpgme_data_seek (dh, 0, SEEK_SET);
43   if (ret)
44     fail_if_err (GPGME_File_Error);
45   while ((ret = gpgme_data_read (dh, buf, 100)) > 0)
46     fwrite (buf, ret, 1, stdout);
47   if (ret < 0)
48     fail_if_err (GPGME_File_Error);
49 }
50
51
52 /* Stripped down version of gpgme/wait.c.  */
53
54 struct op_result
55 {
56   int done;
57   gpgme_error_t err;
58 };
59
60 struct op_result op_result;
61
62 struct one_fd
63 {
64   int fd;
65   int dir;
66   gpgme_io_cb_t fnc;
67   void *fnc_data;
68 };
69
70 #define FDLIST_MAX 32
71 struct one_fd fdlist[FDLIST_MAX];
72
73 gpgme_error_t
74 add_io_cb (void *data, int fd, int dir, gpgme_io_cb_t fnc, void *fnc_data,
75            void **r_tag)
76 {
77   struct one_fd *fds = data;
78   int i;
79
80   for (i = 0; i < FDLIST_MAX; i++)
81     {
82       if (fds[i].fd == -1)
83         {
84           fds[i].fd = fd;
85           fds[i].dir = dir;
86           fds[i].fnc = fnc;
87           fds[i].fnc_data = fnc_data;
88           break;
89         }
90     }
91   if (i == FDLIST_MAX)
92     return GPGME_General_Error;
93   *r_tag = &fds[i];
94   return 0;
95 }
96
97 void
98 remove_io_cb (void *tag)
99 {
100   struct one_fd *fd = tag;
101
102   fd->fd = -1;
103 }
104
105 void
106 io_event (void *data, gpgme_event_io_t type, void *type_data)
107 {
108   struct op_result *result = data;
109
110   if (type == GPGME_EVENT_DONE)
111     {
112       result->done = 1;
113       result->err = * (gpgme_error_t *) type_data;
114     }
115 }
116
117 int
118 do_select (void)
119 {
120   fd_set rfds;
121   fd_set wfds;
122   int i, n;
123   int any = 0;
124
125   FD_ZERO (&rfds);
126   FD_ZERO (&wfds);
127   for (i = 0; i < FDLIST_MAX; i++)
128     if (fdlist[i].fd != -1)
129       FD_SET (fdlist[i].fd, fdlist[i].dir ? &rfds : &wfds);
130
131   do
132     {
133       n = select (FD_SETSIZE, &rfds, &wfds, NULL, 0);
134     }
135   while (n < 0 && errno == EINTR);
136
137   if (n < 0)
138     return n;   /* Error or timeout.  */
139
140   for (i = 0; i < FDLIST_MAX && n; i++)
141     {
142       if (fdlist[i].fd != -1)
143         {
144           if (FD_ISSET (fdlist[i].fd, fdlist[i].dir ? &rfds : &wfds))
145             {
146               assert (n);
147               n--;
148               any = 1;
149               (*fdlist[i].fnc) (fdlist[i].fnc_data, fdlist[i].fd);
150             }
151         }
152     }
153   return any;
154 }
155
156 int
157 my_wait (void)
158 {
159   int n;
160
161   do
162     {
163       n = do_select ();
164     }
165   while (n >= 0 && !op_result.done);
166   return 0;
167 }
168
169 struct gpgme_io_cbs io_cbs =
170   {
171     add_io_cb,
172     fdlist,
173     remove_io_cb,
174     io_event,
175     &op_result
176   };
177
178 int 
179 main (int argc, char *argv[])
180 {
181   gpgme_ctx_t ctx;
182   gpgme_error_t err;
183   gpgme_data_t in, out;
184   gpgme_recipients_t rset;
185   int i;
186
187   for (i = 0; i < FDLIST_MAX; i++)
188     fdlist[i].fd = -1;
189
190   err = gpgme_engine_check_version (GPGME_PROTOCOL_OpenPGP);
191   fail_if_err (err);
192
193   do
194     {
195       err = gpgme_new (&ctx);
196       fail_if_err (err);
197       gpgme_set_armor (ctx, 1);
198       gpgme_set_io_cbs (ctx, &io_cbs);
199       op_result.done = 0;
200
201       err = gpgme_data_new_from_mem (&in, "Hallo Leute\n", 12, 0);
202       fail_if_err (err);
203
204       err = gpgme_data_new (&out);
205       fail_if_err (err);
206
207       err = gpgme_recipients_new (&rset);
208       fail_if_err (err);
209       err = gpgme_recipients_add_name_with_validity (rset, "Bob",
210                                                      GPGME_VALIDITY_FULL);
211       fail_if_err (err);
212       err = gpgme_recipients_add_name_with_validity (rset, "Alpha",
213                                                      GPGME_VALIDITY_FULL);
214       fail_if_err (err);
215
216       err = gpgme_op_encrypt_start (ctx, rset, in, out);
217       fail_if_err (err);
218
219       my_wait ();
220       fail_if_err (op_result.err);
221       fail_if_err (err);
222
223       fflush (NULL);
224       fputs ("Begin Result:\n", stdout);
225       print_data (out);
226       fputs ("End Result.\n", stdout);
227    
228       gpgme_recipients_release (rset);
229       gpgme_data_release (in);
230       gpgme_data_release (out);
231       gpgme_release (ctx);
232     }
233   while (argc > 1 && !strcmp (argv[1], "--loop"));
234
235   return 0;
236 }
237
238