Line data Source code
1 : #if HAVE_CONFIG_H
2 : #include <config.h>
3 : #endif
4 :
5 : #include <assert.h>
6 : #include <stdlib.h>
7 : #include <errno.h>
8 :
9 : #include "assuan.h"
10 :
11 : #include "gpgme.h"
12 : #include "ath.h"
13 : #include "priv-io.h"
14 : #include "debug.h"
15 :
16 :
17 : struct assuan_malloc_hooks _gpgme_assuan_malloc_hooks =
18 : {
19 : malloc,
20 : realloc,
21 : free
22 : };
23 :
24 :
25 : int
26 910 : _gpgme_assuan_log_cb (assuan_context_t ctx, void *hook,
27 : unsigned int cat, const char *msg)
28 : {
29 : (void)ctx;
30 : (void)hook;
31 : (void)cat;
32 :
33 910 : if (msg == NULL)
34 455 : return 1;
35 :
36 455 : _gpgme_debug (DEBUG_ASSUAN, "%s", msg);
37 455 : return 0;
38 : }
39 :
40 :
41 : static void
42 0 : my_usleep (assuan_context_t ctx, unsigned int usec)
43 : {
44 : /* FIXME: Add to ath. */
45 0 : __assuan_usleep (ctx, usec);
46 0 : }
47 :
48 :
49 : /* Create a pipe with an inheritable end. */
50 : static int
51 0 : my_pipe (assuan_context_t ctx, assuan_fd_t fds[2], int inherit_idx)
52 : {
53 : int res;
54 : int gfds[2];
55 :
56 : (void)ctx;
57 :
58 0 : res = _gpgme_io_pipe (gfds, inherit_idx);
59 :
60 : /* For now... */
61 0 : fds[0] = (assuan_fd_t) gfds[0];
62 0 : fds[1] = (assuan_fd_t) gfds[1];
63 :
64 0 : return res;
65 : }
66 :
67 :
68 : /* Close the given file descriptor, created with _assuan_pipe or one
69 : of the socket functions. */
70 : static int
71 18 : my_close (assuan_context_t ctx, assuan_fd_t fd)
72 : {
73 : (void)ctx;
74 18 : return _gpgme_io_close ((int) fd);
75 : }
76 :
77 :
78 : static gpgme_ssize_t
79 24 : my_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
80 : {
81 : (void)ctx;
82 24 : return _gpgme_io_read ((int) fd, buffer, size);
83 : }
84 :
85 :
86 : static gpgme_ssize_t
87 48 : my_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer, size_t size)
88 : {
89 : (void)ctx;
90 48 : return _gpgme_io_write ((int) fd, buffer, size);
91 : }
92 :
93 :
94 : static int
95 124 : my_recvmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
96 : int flags)
97 : {
98 : (void)ctx;
99 : #ifdef HAVE_W32_SYSTEM
100 : (void)fd;
101 : (void)msg;
102 : (void)flags;
103 : gpg_err_set_errno (ENOSYS);
104 : return -1;
105 : #else
106 124 : return _gpgme_io_recvmsg ((int) fd, msg, flags);
107 : #endif
108 : }
109 :
110 :
111 :
112 : static int
113 240 : my_sendmsg (assuan_context_t ctx, assuan_fd_t fd, const assuan_msghdr_t msg,
114 : int flags)
115 : {
116 : (void)ctx;
117 : #ifdef HAVE_W32_SYSTEM
118 : (void)fd;
119 : (void)msg;
120 : (void)flags;
121 : gpg_err_set_errno (ENOSYS);
122 : return -1;
123 : #else
124 240 : return _gpgme_io_sendmsg ((int) fd, msg, flags);
125 : #endif
126 : }
127 :
128 :
129 : /* If NAME is NULL, don't exec, just fork. FD_CHILD_LIST is modified
130 : to reflect the value of the FD in the peer process (on
131 : Windows). */
132 : static int
133 8 : my_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name,
134 : const char **argv,
135 : assuan_fd_t fd_in, assuan_fd_t fd_out,
136 : assuan_fd_t *fd_child_list,
137 : void (*atfork) (void *opaque, int reserved),
138 : void *atforkvalue, unsigned int flags)
139 : {
140 : int err;
141 : struct spawn_fd_item_s *fd_items;
142 : int i;
143 :
144 : (void)ctx;
145 : (void)flags;
146 :
147 8 : assert (name);
148 :
149 8 : if (! name)
150 : {
151 0 : gpg_err_set_errno (ENOSYS);
152 0 : return -1;
153 : }
154 :
155 8 : i = 0;
156 8 : if (fd_child_list)
157 : {
158 24 : while (fd_child_list[i] != ASSUAN_INVALID_FD)
159 8 : i++;
160 : }
161 : /* fd_in, fd_out, terminator */
162 8 : i += 3;
163 8 : fd_items = calloc (i, sizeof (struct spawn_fd_item_s));
164 8 : if (! fd_items)
165 0 : return -1;
166 8 : i = 0;
167 8 : if (fd_child_list)
168 : {
169 24 : while (fd_child_list[i] != ASSUAN_INVALID_FD)
170 : {
171 8 : fd_items[i].fd = (int) fd_child_list[i];
172 8 : fd_items[i].dup_to = -1;
173 8 : i++;
174 : }
175 : }
176 8 : if (fd_in != ASSUAN_INVALID_FD)
177 : {
178 0 : fd_items[i].fd = (int) fd_in;
179 0 : fd_items[i].dup_to = 0;
180 0 : i++;
181 : }
182 8 : if (fd_out != ASSUAN_INVALID_FD)
183 : {
184 0 : fd_items[i].fd = (int) fd_out;
185 0 : fd_items[i].dup_to = 1;
186 0 : i++;
187 : }
188 8 : fd_items[i].fd = -1;
189 8 : fd_items[i].dup_to = -1;
190 :
191 8 : err = _gpgme_io_spawn (name, (char*const*)argv,
192 : (IOSPAWN_FLAG_NOCLOSE | IOSPAWN_FLAG_DETACHED),
193 : fd_items, atfork, atforkvalue, r_pid);
194 8 : if (! err)
195 : {
196 8 : i = 0;
197 :
198 8 : if (fd_child_list)
199 : {
200 24 : while (fd_child_list[i] != ASSUAN_INVALID_FD)
201 : {
202 8 : fd_child_list[i] = (assuan_fd_t) fd_items[i].peer_name;
203 8 : i++;
204 : }
205 : }
206 : }
207 8 : free (fd_items);
208 8 : return err;
209 : }
210 :
211 :
212 : /* If action is 0, like waitpid. If action is 1, just release the PID? */
213 : static pid_t
214 0 : my_waitpid (assuan_context_t ctx, pid_t pid,
215 : int nowait, int *status, int options)
216 : {
217 : (void)ctx;
218 : #ifdef HAVE_W32_SYSTEM
219 : (void)nowait;
220 : (void)status;
221 : (void)options;
222 : CloseHandle ((HANDLE) pid);
223 : #else
224 : /* We can't just release the PID, a waitpid is mandatory. But
225 : NOWAIT in POSIX systems just means the caller already did the
226 : waitpid for this child. */
227 0 : if (! nowait)
228 0 : return _gpgme_ath_waitpid (pid, status, options);
229 : #endif
230 0 : return 0;
231 : }
232 :
233 :
234 :
235 :
236 : static int
237 8 : my_socketpair (assuan_context_t ctx, int namespace, int style,
238 : int protocol, assuan_fd_t filedes[2])
239 : {
240 : #ifdef HAVE_W32_SYSTEM
241 : (void)ctx;
242 : (void)namespace;
243 : (void)style;
244 : (void)protocol;
245 : (void)filedes;
246 : gpg_err_set_errno (ENOSYS);
247 : return -1;
248 : #else
249 : /* FIXME: Debug output missing. */
250 8 : return __assuan_socketpair (ctx, namespace, style, protocol, filedes);
251 : #endif
252 : }
253 :
254 :
255 : static int
256 2 : my_socket (assuan_context_t ctx, int namespace, int style, int protocol)
257 : {
258 : (void)ctx;
259 2 : return _gpgme_io_socket (namespace, style, protocol);
260 : }
261 :
262 :
263 : static int
264 2 : my_connect (assuan_context_t ctx, int sock, struct sockaddr *addr,
265 : socklen_t length)
266 : {
267 : (void)ctx;
268 2 : return _gpgme_io_connect (sock, addr, length);
269 : }
270 :
271 :
272 : /* Note for Windows: Ignore the incompatible pointer type warning for
273 : my_read and my_write. Mingw has been changed to use int for
274 : ssize_t on 32 bit systems while we use long. For 64 bit we use
275 : int64_t while mingw uses __int64_t. It doe not matter at all
276 : because under Windows long and int are both 32 bit even on 64
277 : bit. */
278 : struct assuan_system_hooks _gpgme_assuan_system_hooks =
279 : {
280 : ASSUAN_SYSTEM_HOOKS_VERSION,
281 : my_usleep,
282 : my_pipe,
283 : my_close,
284 : my_read,
285 : my_write,
286 : my_recvmsg,
287 : my_sendmsg,
288 : my_spawn,
289 : my_waitpid,
290 : my_socketpair,
291 : my_socket,
292 : my_connect
293 : };
294 :
|