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