cd9cbc41761f341ae5679b00897120275f78690e
[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
8 #include "assuan.h"
9
10 #include "gpgme.h"
11 #include "ath.h"
12 #include "priv-io.h"
13 #include "debug.h"
14
15 \f
16 struct assuan_malloc_hooks _gpgme_assuan_malloc_hooks =
17   {
18     malloc,
19     realloc,
20     free
21   };
22
23 \f
24 int
25 _gpgme_assuan_log_cb (assuan_context_t ctx, void *hook,
26                       unsigned int cat, const char *msg)
27 {
28   if (msg == NULL)
29     return 1;
30
31   _gpgme_debug (DEBUG_ASSUAN, "%s", msg);
32   return 0;
33 }
34
35 \f
36 static void
37 my_usleep (assuan_context_t ctx, unsigned int usec)
38 {
39   /* FIXME: Add to ath.  */
40   __assuan_usleep (ctx, usec);
41 }
42
43 /* Create a pipe with an inheritable end.  */
44 static int
45 my_pipe (assuan_context_t ctx, assuan_fd_t fds[2], int inherit_idx)
46 {
47   return _gpgme_io_pipe (fds, inherit_idx);
48 }
49
50
51 /* Close the given file descriptor, created with _assuan_pipe or one
52    of the socket functions.  */
53 static int
54 my_close (assuan_context_t ctx, assuan_fd_t fd)
55 {
56   return _gpgme_io_close (fd);
57 }
58
59
60 static ssize_t
61 my_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
62 {
63   return _gpgme_io_read (fd, buffer, size);
64 }
65
66
67 static ssize_t
68 my_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer, size_t size)
69 {
70   return _gpgme_io_write (fd, buffer, size);
71 }
72
73
74 static int
75 my_recvmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
76             int flags)
77 {
78 #ifdef HAVE_W32_SYSTEM
79   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
80 #else
81   return _gpgme_io_recvmsg (fd, msg, flags);
82 #endif
83 }
84
85
86
87 static int
88 my_sendmsg (assuan_context_t ctx, assuan_fd_t fd, const assuan_msghdr_t msg,
89             int flags)
90 {
91 #ifdef HAVE_W32_SYSTEM
92   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
93 #else
94   return _gpgme_io_sendmsg (fd, msg, flags);
95 #endif
96 }
97
98
99 /* If NAME is NULL, don't exec, just fork.  FD_CHILD_LIST is modified
100    to reflect the value of the FD in the peer process (on
101    Windows).  */
102 static int
103 my_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name,
104           const char **argv,
105           assuan_fd_t fd_in, assuan_fd_t fd_out,
106           assuan_fd_t *fd_child_list,
107           void (*atfork) (void *opaque, int reserved),
108           void *atforkvalue, unsigned int flags)
109 {
110   gpg_error_t err;
111   struct spawn_fd_item_s *fd_items;
112   int i;
113
114   assert (name);
115
116   if (! name)
117     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
118
119   i = 0;
120   while (fd_child_list[i] != ASSUAN_INVALID_FD)
121     i++;
122   /* fd_in, fd_out, terminator */
123   i += 3;
124   fd_items = malloc (sizeof (struct spawn_fd_item_s) * i);
125   if (! fd_items)
126     return gpg_error_from_syserror ();
127   i = 0;
128   while (fd_child_list[i] != ASSUAN_INVALID_FD)
129     {
130       fd_items[i].fd = fd_child_list[i];
131       fd_items[i].dup_to = -1;
132       i++;
133     }
134   if (fd_in != ASSUAN_INVALID_FD)
135     {
136       fd_items[i].fd = fd_in;
137       fd_items[i].dup_to = 0;
138       i++;
139     }
140   if (fd_out != ASSUAN_INVALID_FD)
141     {
142       fd_items[i].fd = fd_out;
143       fd_items[i].dup_to = 1;
144       i++;
145     }
146   fd_items[i].fd = -1;
147   fd_items[i].dup_to = -1;
148
149   err = _gpgme_io_spawn (name, argv, 0, fd_items, r_pid);
150   if (! err)
151     {
152       i = 0;
153
154       while (fd_child_list[i] != ASSUAN_INVALID_FD)
155         {
156           fd_child_list[i] = fd_items[i].peer_name;
157           i++;
158         }
159     }
160   free (fd_items);
161   return err;
162 }
163
164
165 /* If action is 0, like waitpid.  If action is 1, just release the PID?  */
166 static pid_t
167 my_waitpid (assuan_context_t ctx, pid_t pid,
168             int nowait, int *status, int options)
169 {
170 #ifdef HAVE_W32_SYSTEM
171   CloseHandle ((HANDLE) pid);
172 #else
173   /* We can't just release the PID, a waitpid is mandatory.  But
174      NOWAIT in POSIX systems just means the caller already did the
175      waitpid for this child.  */
176   if (! nowait)
177     return _gpgme_ath_waitpid (pid, status, options); 
178 #endif
179   return 0;
180 }
181
182
183
184
185 static int
186 my_socketpair (assuan_context_t ctx, int namespace, int style,
187                int protocol, assuan_fd_t filedes[2])
188 {
189   assert ("Should never happen.");
190   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
191 }
192
193
194 struct assuan_system_hooks _gpgme_assuan_system_hooks =
195   {
196     ASSUAN_SYSTEM_HOOKS_VERSION,
197     my_usleep,
198     my_pipe,
199     my_close,
200     my_read,
201     my_write,
202     my_recvmsg,
203     my_sendmsg,
204     my_spawn,
205     my_waitpid,
206     my_socketpair
207   };
208