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