#if HAVE_CONFIG_H #include #endif #include #include #include #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 };