summaryrefslogtreecommitdiff
path: root/src/assuan-support.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/assuan-support.c')
-rw-r--r--src/assuan-support.c256
1 files changed, 256 insertions, 0 deletions
diff --git a/src/assuan-support.c b/src/assuan-support.c
new file mode 100644
index 0000000..5264346
--- /dev/null
+++ b/src/assuan-support.c
@@ -0,0 +1,256 @@
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "assuan.h"
+
+#include "gpgme.h"
+#include "ath.h"
+#include "priv-io.h"
+#include "debug.h"
+
+
+struct assuan_malloc_hooks _gpgme_assuan_malloc_hooks =
+ {
+ malloc,
+ realloc,
+ free
+ };
+
+
+int
+_gpgme_assuan_log_cb (assuan_context_t ctx, void *hook,
+ unsigned int cat, const char *msg)
+{
+ if (msg == NULL)
+ return 1;
+
+ _gpgme_debug (DEBUG_ASSUAN, "%s", msg);
+ return 0;
+}
+
+
+static void
+my_usleep (assuan_context_t ctx, unsigned int usec)
+{
+ /* FIXME: Add to ath. */
+ __assuan_usleep (ctx, usec);
+}
+
+
+/* Create a pipe with an inheritable end. */
+static int
+my_pipe (assuan_context_t ctx, assuan_fd_t fds[2], int inherit_idx)
+{
+ int res;
+ int gfds[2];
+
+ res = _gpgme_io_pipe (gfds, inherit_idx);
+
+ /* For now... */
+ fds[0] = (assuan_fd_t) gfds[0];
+ fds[1] = (assuan_fd_t) gfds[1];
+
+ return res;
+}
+
+
+/* Close the given file descriptor, created with _assuan_pipe or one
+ of the socket functions. */
+static int
+my_close (assuan_context_t ctx, assuan_fd_t fd)
+{
+ return _gpgme_io_close ((int) fd);
+}
+
+
+static ssize_t
+my_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
+{
+ return _gpgme_io_read ((int) fd, buffer, size);
+}
+
+
+static ssize_t
+my_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer, size_t size)
+{
+ return _gpgme_io_write ((int) fd, buffer, size);
+}
+
+
+static int
+my_recvmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
+ int flags)
+{
+#ifdef HAVE_W32_SYSTEM
+ gpg_err_set_errno (ENOSYS);
+ return -1;
+#else
+ return _gpgme_io_recvmsg ((int) fd, msg, flags);
+#endif
+}
+
+
+
+static int
+my_sendmsg (assuan_context_t ctx, assuan_fd_t fd, const assuan_msghdr_t msg,
+ int flags)
+{
+#ifdef HAVE_W32_SYSTEM
+ gpg_err_set_errno (ENOSYS);
+ return -1;
+#else
+ return _gpgme_io_sendmsg ((int) fd, msg, flags);
+#endif
+}
+
+
+/* If NAME is NULL, don't exec, just fork. FD_CHILD_LIST is modified
+ to reflect the value of the FD in the peer process (on
+ Windows). */
+static int
+my_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name,
+ const char **argv,
+ assuan_fd_t fd_in, assuan_fd_t fd_out,
+ assuan_fd_t *fd_child_list,
+ void (*atfork) (void *opaque, int reserved),
+ void *atforkvalue, unsigned int flags)
+{
+ int err;
+ struct spawn_fd_item_s *fd_items;
+ int i;
+
+ assert (name);
+
+ if (! name)
+ {
+ gpg_err_set_errno (ENOSYS);
+ return -1;
+ }
+
+ i = 0;
+ if (fd_child_list)
+ {
+ while (fd_child_list[i] != ASSUAN_INVALID_FD)
+ i++;
+ }
+ /* fd_in, fd_out, terminator */
+ i += 3;
+ fd_items = calloc (i, sizeof (struct spawn_fd_item_s));
+ if (! fd_items)
+ return -1;
+ i = 0;
+ if (fd_child_list)
+ {
+ while (fd_child_list[i] != ASSUAN_INVALID_FD)
+ {
+ fd_items[i].fd = (int) fd_child_list[i];
+ fd_items[i].dup_to = -1;
+ i++;
+ }
+ }
+ if (fd_in != ASSUAN_INVALID_FD)
+ {
+ fd_items[i].fd = (int) fd_in;
+ fd_items[i].dup_to = 0;
+ i++;
+ }
+ if (fd_out != ASSUAN_INVALID_FD)
+ {
+ fd_items[i].fd = (int) fd_out;
+ fd_items[i].dup_to = 1;
+ i++;
+ }
+ fd_items[i].fd = -1;
+ fd_items[i].dup_to = -1;
+
+ err = _gpgme_io_spawn (name, (char*const*)argv, IOSPAWN_FLAG_NOCLOSE,
+ fd_items, atfork, atforkvalue, r_pid);
+ if (! err)
+ {
+ i = 0;
+
+ if (fd_child_list)
+ {
+ while (fd_child_list[i] != ASSUAN_INVALID_FD)
+ {
+ fd_child_list[i] = (assuan_fd_t) fd_items[i].peer_name;
+ i++;
+ }
+ }
+ }
+ free (fd_items);
+ return err;
+}
+
+
+/* If action is 0, like waitpid. If action is 1, just release the PID? */
+static pid_t
+my_waitpid (assuan_context_t ctx, pid_t pid,
+ int nowait, int *status, int options)
+{
+#ifdef HAVE_W32_SYSTEM
+ CloseHandle ((HANDLE) pid);
+#else
+ /* We can't just release the PID, a waitpid is mandatory. But
+ NOWAIT in POSIX systems just means the caller already did the
+ waitpid for this child. */
+ if (! nowait)
+ return _gpgme_ath_waitpid (pid, status, options);
+#endif
+ return 0;
+}
+
+
+
+
+static int
+my_socketpair (assuan_context_t ctx, int namespace, int style,
+ int protocol, assuan_fd_t filedes[2])
+{
+#ifdef HAVE_W32_SYSTEM
+ gpg_err_set_errno (ENOSYS);
+ return -1;
+#else
+ /* FIXME: Debug output missing. */
+ return __assuan_socketpair (ctx, namespace, style, protocol, filedes);
+#endif
+}
+
+
+static int
+my_socket (assuan_context_t ctx, int namespace, int style, int protocol)
+{
+ return _gpgme_io_socket (namespace, style, protocol);
+}
+
+
+static int
+my_connect (assuan_context_t ctx, int sock, struct sockaddr *addr,
+ socklen_t length)
+{
+ return _gpgme_io_connect (sock, addr, length);
+}
+
+
+struct assuan_system_hooks _gpgme_assuan_system_hooks =
+ {
+ ASSUAN_SYSTEM_HOOKS_VERSION,
+ my_usleep,
+ my_pipe,
+ my_close,
+ my_read,
+ my_write,
+ my_recvmsg,
+ my_sendmsg,
+ my_spawn,
+ my_waitpid,
+ my_socketpair,
+ my_socket,
+ my_connect
+ };
+