summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Brinkmann <mb@g10code.com>2009-10-16 18:24:46 +0000
committerMarcus Brinkmann <mb@g10code.com>2009-10-16 18:24:46 +0000
commit5e15cf931706f9a6ae00d17569b97d636d6f2945 (patch)
tree5feff75cb4dabe4b198089ca05314e6ad5f8d827
parent1dce00882d78e0bb30011067f383583f2b551172 (diff)
downloadlibassuan-5e15cf931706f9a6ae00d17569b97d636d6f2945.tar.gz
2009-10-16 Marcus Brinkmann <marcus@g10code.de>
* autogen.sh: Remove --with-pth-prefix from configure invocation. * configure.ac (_ASSUAN_IN_LIBASSUAN, PTH_SYSCALL_SOFT): Do not set anymore. (GNUPG_PATH_PTH): Don't invoke. (HAVE_PTH): Remove conditional. (LIBASSUAN_CONFIG_THREAD_MODULES): Removed. doc/ 2009-10-16 Marcus Brinkmann <marcus@g10code.com> * assuan.texi: Remove documentation for thread support. (assuan_pipe_connect_ext): Update prototype. src/ 2009-10-16 Marcus Brinkmann <marcus@g10code.com> * conversion.c: Do not include <sys/types.h> and <time.h>. * debug.h (TRACE_BEG6, TRACE4): New macros. (TRACE_SYSERR): Pass _assuan_trace_context to _assuan_debug. * context.c (assuan_set_pointer, assuan_get_pointer, assuan_set_flag, assuan_get_flag, assuan_set_io_monitor, assuan_set_error): Add trace messages. * libassuan-config.in, libassuan.m4, Makefile.am: Remove PTH support. * assuan.h (assuan_msghdr_t): New type. (ASSUAN_INVALID_PID): New macro. (ASSUAN_NO_FIXSIGNALS): New flag macro. (ASSUAN_SYSTEM_HOOKS_VERSION): New macro. (struct assuan_system_hooks, assuan_system_hooks_t): New types. (assuan_pipe_connect, assuan_pipe_connect_ext): Don't make ARGV const for name==NULL operation. Make fd_child_list an array of assuan_fd_t. (assuan_sock_init, assuan_sock_deinit, assuan_set_system_hooks, assuan_ctx_set_system_hooks, __assuan_pipe, __assuan_close, __assuan_spawn, __assuan_socketpair): New function prototypes. (_ASSUAN_SYSTEM_PTH_IMPL, ASSUAN_SYSTEM_PTH_DECL, ASSUAN_SYSTEM_PTH): New macros. (_assuan_system_pth): New declaration. * libassuan.vers, libassuan.defs: Add assuan_sock_init, assuan_sock_deinit, __assuan_pipe, __assuan_close, __assuan_spawn, __assuan_socketpair, assuan_set_system_hooks, assuan_ctx_set_system_hooks. * assuan-defs.h (struct assuan_io): Removed, move members to ... (struct assuan_context_s): ... this to ENGINE. New flag no_fixsignals. New member SYSTEM. Remove member IO. (_assuan_pipe, _assuan_read, _assuan_write, _assuan_recvmsg, _assuan_sendmsg, _assuan_spawn, _assuan_socketpair, _assuan_system_hooks, _assuan_system_hooks_copy): New declarations. (_assuan_error_is_eagain, _assuan_waitpid, _assuan_usleep, _assuan_close, _assuan_sock_new, _assuan_sock_connect, _assuan_sock_bind, _assuan_sock_get_nonce, _assuan_sock_check_nonce): Add context argument. (_assuan_io_read, _assuan_io_write, _assuan_simple_sendmsg, _assuan_simple_recvmsg): Removed. * context.c (assuan_ctx_set_system_hooks): New function. * assuan.c (assuan_set_system_hooks): New function. (assuan_new_ext): Initialize CTX->system. (assuan_release): Always output trace message. * assuan-error.c (_assuan_error_is_eagain): Add ctx argument, pass along to _assuan_usleep. * assuan-inquire.c assuan-listen.c, assuan-socket-server.c, assuan-handler.c, assuan-socket-connect.c, assuan-client.c, assuan-pipe-connect.c, assuan-socket.c: Pass CTX argument to functions that need it (_assuan_sock_new, _assuan_sock_check_none, _assuan_close, _assuan_error_is_eagain and many more). * assuan-socket-server.c (assuan_init_socket_server_ext): Update fields in CTX->engine instead of CTX->io. * assuan-socket-connect (assuan_socket_connect_ext): Likewise. * assuan-uds.c (uds_reader, uds_writer, uds_sendfd): Use _assuan_recvmsg and _assuan_sendmsg instead of _assuan_simple_recvmsg and _assuan_simple_sendmsg respectively. (_assuan_init_uds_io): Update fields in CTX->engine instead of CTX->io. * assuan-buffer.c: Use functions in CTX->engine instead of CTX->io. * assuan-pipe-server.c (assuan_init_pipe_server): Update fields in CTX->engine instead of CTX->io. * system.c: Include <sys/types.h>, <time.h>, <fcntl.h>, and <windows.h> resp. <sys/wait.h>. Define MAX_OPEN_FDS. (_assuan_system_hooks_copy, __assuan_usleep, _assuan_usleep, __assuan_pipe, _assuan_pipe, __assuan_close, _assuan_close, __assuan_read, _assuan_read, __assuan_write, _assuan_write, __assuan_recvmsg, _assuan_recvmsg, __assuan_sendmsg, _assuan_sendmsg, __assuan_spawn, _assuan_spawn, __assuan_waitpid, _assuan_waitpid, __assuan_socketpair, _assuan_socketpair): New functions. (_assuan_system_hooks): New singleton. * assuan-io.c (_assuan_waitpid, do_io_read, _assuan_io_read, do_io_write, _assuan_io_write, _assuan_simple_sendmsg, _assuan_simple_recvmsg, _assuan_usleep): Removed. * assuan-pipe-connect (writen, build_w32_commandline, create_inheritable_pipe): Removed (actually moved to system.c). (fix_signals) [_ASSUAN_NO_FIXED_SIGNALS]: Still fix signals. (do_finish): Move waitpid logic to _assuan_waitpid, just call that. (struct at_pipe_fork, struct at_socketpair_fork): New types. (at_pipe_fork_cb, at_socketpair_fork_cb): New callback functions. (pipe_connect_unix, pipe_connect_w32): Replaced by ... (pipe_connect): ... this new function using new system functions. (socketpair_connect): Reimplement to use new system functions. (assuan_pipe_connect, assuan_pipe_connect_ext): Add trace message. * assuan-socket.c (_assuan_close): Removed (moved to system.c). (_assuan_sock_new, _assuan_sock_connect, _assuan_sock_bind, _assuan_sock_get_nonce, _assuan_sock_check_nonce): Add context argument. Use new system interface. (sock_ctx): New singleton. (assuan_sock_init, assuan_sock_deinit): New functions to initialize and deinitialize the singleton.
-rw-r--r--ChangeLog9
-rw-r--r--NEWS18
-rwxr-xr-xautogen.sh1
-rw-r--r--configure.ac23
-rw-r--r--doc/ChangeLog5
-rw-r--r--doc/assuan.texi39
-rw-r--r--src/ChangeLog114
-rw-r--r--src/Makefile.am16
-rw-r--r--src/assuan-buffer.c14
-rw-r--r--src/assuan-client.c2
-rw-r--r--src/assuan-defs.h96
-rw-r--r--src/assuan-error.c6
-rw-r--r--src/assuan-handler.c8
-rw-r--r--src/assuan-inquire.c2
-rw-r--r--src/assuan-io-pth.c170
-rw-r--r--src/assuan-io.c174
-rw-r--r--src/assuan-listen.c4
-rw-r--r--src/assuan-pipe-connect.c779
-rw-r--r--src/assuan-pipe-server.c8
-rw-r--r--src/assuan-socket-connect.c17
-rw-r--r--src/assuan-socket-server.c15
-rw-r--r--src/assuan-socket.c103
-rw-r--r--src/assuan-uds.c17
-rw-r--r--src/assuan.c26
-rw-r--r--src/assuan.h207
-rw-r--r--src/context.c64
-rw-r--r--src/conversion.c5
-rw-r--r--src/debug.h12
-rw-r--r--src/libassuan-config.in27
-rw-r--r--src/libassuan.def9
-rw-r--r--src/libassuan.m442
-rw-r--r--src/libassuan.vers8
-rw-r--r--src/system.c805
33 files changed, 1599 insertions, 1246 deletions
diff --git a/ChangeLog b/ChangeLog
index dbf7b47..7253adc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2009-10-16 Marcus Brinkmann <marcus@g10code.de>
+
+ * autogen.sh: Remove --with-pth-prefix from configure invocation.
+ * configure.ac (_ASSUAN_IN_LIBASSUAN, PTH_SYSCALL_SOFT): Do not
+ set anymore.
+ (GNUPG_PATH_PTH): Don't invoke.
+ (HAVE_PTH): Remove conditional.
+ (LIBASSUAN_CONFIG_THREAD_MODULES): Removed.
+
2009-10-08 Marcus Brinkmann <marcus@g10code.de>
* configure.ac: AC_REPLACE_FUNCS for vasprintf.
diff --git a/NEWS b/NEWS
index 46042f2..32b79e8 100644
--- a/NEWS
+++ b/NEWS
@@ -13,7 +13,11 @@ Noteworthy changes in version 1.1.0 (unreleased)
If you use assuan_pipe_connect or assuan_pipe_connect_ext with NAME
of NULL, you have to provide a non-NULL ARGV argument and check
that against "server" or "client" to determine which end you got
- after fork().
+ after fork(). If you use the assuan sock interface, you must call
+ assuan_sock_init after setting global context defaults.
+
+ * Pth support has changed. This now follows the same style as
+ libgcrypt by setting system hook callbacks.
* Interface changes relative to the 1.0.5 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -51,6 +55,18 @@ assuan_set_io_hooks REMOVED: Will come back in expanded form.
assuan_io_hooks_t REMOVED: Will come back in expanded form.
assuan_io_monitor_t CHANGED: Add a hook data argument.
assuan_get_command_name NEW
+assuan_msghdr_t NEW
+ASSUAN_INVALID_PID NEW
+ASSUAN_NO_FIXSIGNALS NEW
+ASSUAN_SYSTEM_HOOKS_VERSION NEW
+assuan_system_hooks_t NEW
+assuan_set_system_hooks NEW
+assuan_ctx_set_system_hooks NEW
+ASSUAN_SYSTEM_PTH_IMPL NEW
+ASSUAN_SYSTEM_PTH_DECL NEW
+ASSUAN_SYSTEM_PTH NEW
+assuan_sock_init NEW
+assuan_sock_deinit NEW
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/autogen.sh b/autogen.sh
index 1b837c6..5300c6f 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -77,7 +77,6 @@ if test "$1" = "--build-w32"; then
./configure --enable-maintainer-mode --prefix=${w32root} \
--host=${host} --build=${build} \
- --with-pth-prefix=${w32root} \
--disable-shared
exit $?
diff --git a/configure.ac b/configure.ac
index dce02ad..b6353eb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
# configure.ac - for libassuan
-# Copyright (C) 2001, 2002, 2003, 2006, 2007 Free Software Foundation, Inc.
+# Copyright (C) 2001-2003, 2006, 2007, 2009 Free Software Foundation, Inc.
#
# This file is part of Assuan.
#
@@ -132,16 +132,6 @@ if test "$GCC" = yes; then
fi
-AH_BOTTOM([
-#define _ASSUAN_IN_LIBASSUAN 1
-
-/* We explicitly need to disable PTH's soft mapping as Debian
- currently enables it by default for no reason. */
-#define PTH_SYSCALL_SOFT 0
-
-])
-
-
#
# Options depending on the host OS.
#
@@ -191,12 +181,6 @@ AC_SUBST(BUILD_TIMESTAMP)
AC_SUBST(BUILD_FILEVERSION)
AM_CONDITIONAL(HAVE_W32_SYSTEM, test "$have_w32_system" = yes)
-#
-# See whether we can build a Pth enabled version
-#
-GNUPG_PATH_PTH
-AM_CONDITIONAL(HAVE_PTH, test "$have_pth" = "yes")
-
# Check for network libraries. They are needed for tests.
AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt,
@@ -211,10 +195,6 @@ fi
# For src/libassuan-config.in
LIBASSUAN_CONFIG_LIB="-lassuan"
LIBASSUAN_CONFIG_CFLAGS=""
-LIBASSUAN_CONFIG_THREAD_MODULES=
-if test "$have_pth" = yes; then
-LIBASSUAN_CONFIG_THREAD_MODULES="pth"
-fi
LIBASSUAN_CONFIG_EXTRA_LIBS=
if test x"$NETLIBS" != x; then
LIBASSUAN_CONFIG_EXTRA_LIBS="$LIBASSUAN_CONFIG_EXTRA_LIBS $NETLIBS"
@@ -222,7 +202,6 @@ fi
AC_SUBST(LIBASSUAN_CONFIG_LIB)
AC_SUBST(LIBASSUAN_CONFIG_CFLAGS)
AC_SUBST(LIBASSUAN_CONFIG_API_VERSION)
-AC_SUBST(LIBASSUAN_CONFIG_THREAD_MODULES)
AC_SUBST(LIBASSUAN_CONFIG_EXTRA_LIBS)
# Checks for header files.
diff --git a/doc/ChangeLog b/doc/ChangeLog
index c567640..6106e35 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,8 @@
+2009-10-16 Marcus Brinkmann <marcus@g10code.com>
+
+ * assuan.texi: Remove documentation for thread support.
+ (assuan_pipe_connect_ext): Update prototype.
+
2009-10-14 Werner Koch <wk@g10code.com>
* assuan.texi (Utilities): Describe assuan_get_command_name.
diff --git a/doc/assuan.texi b/doc/assuan.texi
index adfc86d..5641aa0 100644
--- a/doc/assuan.texi
+++ b/doc/assuan.texi
@@ -465,10 +465,6 @@ specifying both options to @command{libassuan-config}:
gcc -o foo foo.c $(libassuan-config --cflags --libs)
@end example
-If your application uses Pth or pthread, you need to pass the option
-@option{--thread=pth} respective @option{--thread=pthread} to the
-invocation of @command{libassuan-config}.
-
@node Automake
@section Building sources using Automake
@@ -498,36 +494,27 @@ AM_CPPFLAGS = $(LIBASSUAN_CFLAGS)
LDADD = $(LIBASSUAN_LIBS)
@end example
-@defmac AM_PATH_LIBASSUAN_PTH (@ovar{minimum-version}, @ovar{action-if-found}, @ovar{action-if-not-found})
-Same as @code{AM_PATH_LIBASSUAN} but checks for the GNU Pth enabled
-version of the library and defines @code{LIBASSUAN_PTH_CFLAGS}
-@code{LIBASSUAN_PTH_LIBS} instead. Use this is you are using GNU Pth.
-Note that you also need to pass the appropriate options for Pth to the
-compiler and linker.
-@end defmac
-
-@defmac AM_PATH_LIBASSUAN_PTHREAD (@ovar{minimum-version}, @ovar{action-if-found}, @ovar{action-if-not-found})
-Same as @code{AM_PATH_LIBASSUAN} but checks for the pthreads enabled
-version of the library and defines @code{LIBASSUAN_PTHREAD_CFLAGS}
-@code{LIBASSUAN_PTHREAD_LIBS} instead. Use this is you are using GNU Pth.
-Note that you also need to pass the appropriate options for Pth to the
-compiler and linker.
-@end defmac
-
-
@node Multi Threading
@section Multi Threading
-The @code{libassuan} library is thread-safe if you adhere to the following
-requirements:
+The @code{libassuan} library is designed so that it can be used in a
+threaded application, if some rules are followed.
@itemize @bullet
@item Run the initialization functions before you actually start
-to use threads.
+to use threads. Specifically, the functions
+@code{assuan_set_gpg_err_source}, @code{assuan_set_malloc_hooks} and
+@code{assuan_set_log_cb} should not be called concurrently with
+@code{assuan_new}. Use @code{assuan_new_ext} instead or ensure proper
+serialization.
@item Only one thread at a time may access an @code{libassuan} context.
@item If you use the default log handler, use
@code{assuan_set_assuan_log_stream} to setup a default log stream.
+@item If you have callback functions shared by multiple functions,
+the callback function must be reentrant for that purpose.
+@code{libassuan} does not serialize invocation of callback functions
+across contexts.
@end itemize
@@ -950,12 +937,12 @@ If the peer is not a simple pipe server but one using full-duplex
sockets, the full-fledged variant of the above function should be
used:
-@deftypefun gpg_error_t assuan_pipe_connect_ext (@w{assuan_context_t *@var{ctx}},@w{const char *@var{name}}, @w{const char *@var{argv}[]}, @w{int *@var{fd_child_list}}, @w{void (*@var{atfork}) (void *, int)}, @w{void *@var{atforkvalue}}, @w{unsigned int @var{flags}})
+@deftypefun gpg_error_t assuan_pipe_connect_ext (@w{assuan_context_t *@var{ctx}},@w{const char *@var{name}}, @w{const char *@var{argv}[]}, @w{assuan_fd_t *@var{fd_child_list}}, @w{void (*@var{atfork}) (void *, int)}, @w{void *@var{atforkvalue}}, @w{unsigned int @var{flags}})
A call to this functions forks the current process and executes the
program @var{name}, passing the arguments given in the NULL-terminated
list @var{argv}. A list of file descriptors not to be closed may be
-given using the @code{-1} terminated array @var{fd_child_list}.
+given using the @code{ASSUAN_INVLID_FD} terminated array @var{fd_child_list}.
If @var{name} is a null pointer, only a fork but no exec is done.
Thus the child continues to run. However all file descriptors are
diff --git a/src/ChangeLog b/src/ChangeLog
index c9f2172..0d22b02 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,105 @@
+2009-10-16 Marcus Brinkmann <marcus@g10code.com>
+
+ * conversion.c: Do not include <sys/types.h> and <time.h>.
+ * debug.h (TRACE_BEG6, TRACE4): New macros.
+ (TRACE_SYSERR): Pass _assuan_trace_context to _assuan_debug.
+ * context.c (assuan_set_pointer, assuan_get_pointer,
+ assuan_set_flag, assuan_get_flag, assuan_set_io_monitor,
+ assuan_set_error): Add trace messages.
+
+ * libassuan-config.in, libassuan.m4, Makefile.am: Remove PTH support.
+ * assuan.h (assuan_msghdr_t): New type.
+ (ASSUAN_INVALID_PID): New macro.
+ (ASSUAN_NO_FIXSIGNALS): New flag macro.
+ (ASSUAN_SYSTEM_HOOKS_VERSION): New macro.
+ (struct assuan_system_hooks, assuan_system_hooks_t): New types.
+ (assuan_pipe_connect, assuan_pipe_connect_ext): Don't make ARGV
+ const for name==NULL operation. Make fd_child_list an array of
+ assuan_fd_t.
+ (assuan_sock_init, assuan_sock_deinit, assuan_set_system_hooks,
+ assuan_ctx_set_system_hooks, __assuan_pipe, __assuan_close,
+ __assuan_spawn, __assuan_socketpair): New function prototypes.
+ (_ASSUAN_SYSTEM_PTH_IMPL, ASSUAN_SYSTEM_PTH_DECL,
+ ASSUAN_SYSTEM_PTH): New macros.
+ (_assuan_system_pth): New declaration.
+ * libassuan.vers, libassuan.defs: Add assuan_sock_init,
+ assuan_sock_deinit, __assuan_pipe, __assuan_close, __assuan_spawn,
+ __assuan_socketpair, assuan_set_system_hooks,
+ assuan_ctx_set_system_hooks.
+
+ * assuan-defs.h (struct assuan_io): Removed, move members to ...
+ (struct assuan_context_s): ... this to ENGINE. New flag
+ no_fixsignals. New member SYSTEM. Remove member IO.
+ (_assuan_pipe, _assuan_read, _assuan_write, _assuan_recvmsg,
+ _assuan_sendmsg, _assuan_spawn, _assuan_socketpair,
+ _assuan_system_hooks, _assuan_system_hooks_copy): New
+ declarations.
+ (_assuan_error_is_eagain, _assuan_waitpid, _assuan_usleep,
+ _assuan_close, _assuan_sock_new, _assuan_sock_connect,
+ _assuan_sock_bind, _assuan_sock_get_nonce,
+ _assuan_sock_check_nonce): Add context argument.
+ (_assuan_io_read, _assuan_io_write, _assuan_simple_sendmsg,
+ _assuan_simple_recvmsg): Removed.
+
+ * context.c (assuan_ctx_set_system_hooks): New function.
+ * assuan.c (assuan_set_system_hooks): New function.
+ (assuan_new_ext): Initialize CTX->system.
+ (assuan_release): Always output trace message.
+
+ * assuan-error.c (_assuan_error_is_eagain): Add ctx argument, pass
+ along to _assuan_usleep.
+ * assuan-inquire.c assuan-listen.c, assuan-socket-server.c,
+ assuan-handler.c, assuan-socket-connect.c, assuan-client.c,
+ assuan-pipe-connect.c, assuan-socket.c: Pass CTX argument to
+ functions that need it
+ (_assuan_sock_new, _assuan_sock_check_none, _assuan_close,
+ _assuan_error_is_eagain and many more).
+ * assuan-socket-server.c (assuan_init_socket_server_ext): Update
+ fields in CTX->engine instead of CTX->io.
+ * assuan-socket-connect (assuan_socket_connect_ext): Likewise.
+ * assuan-uds.c (uds_reader, uds_writer, uds_sendfd): Use
+ _assuan_recvmsg and _assuan_sendmsg instead of
+ _assuan_simple_recvmsg and _assuan_simple_sendmsg respectively.
+ (_assuan_init_uds_io): Update fields in CTX->engine instead of
+ CTX->io.
+ * assuan-buffer.c: Use functions in CTX->engine instead of CTX->io.
+ * assuan-pipe-server.c (assuan_init_pipe_server): Update
+ fields in CTX->engine instead of CTX->io.
+
+ * system.c: Include <sys/types.h>, <time.h>, <fcntl.h>, and
+ <windows.h> resp. <sys/wait.h>. Define MAX_OPEN_FDS.
+ (_assuan_system_hooks_copy, __assuan_usleep, _assuan_usleep,
+ __assuan_pipe, _assuan_pipe, __assuan_close, _assuan_close,
+ __assuan_read, _assuan_read, __assuan_write, _assuan_write,
+ __assuan_recvmsg, _assuan_recvmsg, __assuan_sendmsg,
+ _assuan_sendmsg, __assuan_spawn, _assuan_spawn, __assuan_waitpid,
+ _assuan_waitpid, __assuan_socketpair, _assuan_socketpair): New
+ functions.
+ (_assuan_system_hooks): New singleton.
+ * assuan-io.c (_assuan_waitpid, do_io_read, _assuan_io_read,
+ do_io_write, _assuan_io_write, _assuan_simple_sendmsg,
+ _assuan_simple_recvmsg, _assuan_usleep): Removed.
+
+ * assuan-pipe-connect (writen, build_w32_commandline,
+ create_inheritable_pipe): Removed (actually moved to system.c).
+ (fix_signals) [_ASSUAN_NO_FIXED_SIGNALS]: Still fix signals.
+ (do_finish): Move waitpid logic to _assuan_waitpid, just call
+ that.
+ (struct at_pipe_fork, struct at_socketpair_fork): New types.
+ (at_pipe_fork_cb, at_socketpair_fork_cb): New callback functions.
+ (pipe_connect_unix, pipe_connect_w32): Replaced by ...
+ (pipe_connect): ... this new function using new system functions.
+ (socketpair_connect): Reimplement to use new system functions.
+ (assuan_pipe_connect, assuan_pipe_connect_ext): Add trace message.
+
+ * assuan-socket.c (_assuan_close): Removed (moved to system.c).
+ (_assuan_sock_new, _assuan_sock_connect, _assuan_sock_bind,
+ _assuan_sock_get_nonce, _assuan_sock_check_nonce): Add context
+ argument. Use new system interface.
+ (sock_ctx): New singleton.
+ (assuan_sock_init, assuan_sock_deinit): New functions to
+ initialize and deinitialize the singleton.
+
2009-10-14 Werner Koch <wk@g10code.com>
* assuan-defs.h (assuan_context_s): Add field CURRENT_CMD_NAME.
@@ -7,6 +109,18 @@
2009-10-08 Marcus Brinkmann <marcus@g10code.de>
+ * Makefile.am (libassuan_pth): Removed.
+ (lib_LTLIBRARIES): Remove $(libassuan_pth).
+ (libassuan_pth_la_SOURCES, libassuan_pth_la_CPPFLAGS)
+ (libassuan_pth_la_CFLAGS, libassuan_pth_la_LIBADD): Removed.
+ * libassuan.m4 (AM_PATH_LIBASSUAN_PTH, AM_PATH_LIBASSUAN_PTHREAD):
+ Removed.
+ * assuan-io-pth.c: Removed.
+ * libassuan-config.in (all_thread_modules): Removed. Also removed
+ option --thread.
+
+2009-10-08 Marcus Brinkmann <marcus@g10code.de>
+
* assuan.h (assuan_get_assuan_log_stream,
assuan_set_assuan_log_stream): Remove prototypes.
* libassuan.def: Remove assuan_get_assuan_log_stream,
diff --git a/src/Makefile.am b/src/Makefile.am
index 1e1c46b..bfbcfec 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -21,16 +21,10 @@ EXTRA_DIST = libassuan-config.in libassuan.m4 libassuan.vers \
versioninfo.rc.in libassuan.def
INCLUDES = -I.. -I$(top_srcdir)/include
-if HAVE_PTH
-libassuan_pth = libassuan-pth.la
-else
-libassuan_pth =
-endif
-
bin_SCRIPTS = libassuan-config
m4datadir = $(datadir)/aclocal
m4data_DATA = libassuan.m4
-lib_LTLIBRARIES = libassuan.la $(libassuan_pth)
+lib_LTLIBRARIES = libassuan.la
include_HEADERS = assuan.h
if HAVE_LD_VERSION_SCRIPT
@@ -107,11 +101,3 @@ libassuan_la_LDFLAGS = $(libassuan_res_ldflag) $(no_undefined) \
libassuan_la_DEPENDENCIES = @LTLIBOBJS@ \
$(srcdir)/libassuan.vers $(libassuan_deps)
libassuan_la_LIBADD = @LTLIBOBJS@ @NETLIBS@ @GPG_ERROR_LIBS@
-
-if HAVE_PTH
-libassuan_pth_la_SOURCES = $(common_sources) assuan-io-pth.c
-libassuan_pth_la_CPPFLAGS = $(AM_CPPFLAGS) @GPG_ERROR_CFLAGS@ @PTH_CFLAGS@
-libassuan_pth_la_CFLAGS = $(AM_CFLAGS) @GPG_ERROR_CFLAGS@ $(PTH_CFLAGS)
-libassuan_pth_la_LIBADD = @LTLIBOBJS@ @NETLIBS@ @GPG_ERROR_LIBS@ @PTH_LIBS@
-endif
-
diff --git a/src/assuan-buffer.c b/src/assuan-buffer.c
index 583d137..32a9aee 100644
--- a/src/assuan-buffer.c
+++ b/src/assuan-buffer.c
@@ -37,7 +37,7 @@ writen (assuan_context_t ctx, const char *buffer, size_t length)
{
while (length)
{
- ssize_t nwritten = ctx->io->writefnc (ctx, buffer, length);
+ ssize_t nwritten = ctx->engine.writefnc (ctx, buffer, length);
if (nwritten < 0)
{
@@ -66,7 +66,7 @@ readline (assuan_context_t ctx, char *buf, size_t buflen,
*r_nread = 0;
while (nleft > 0)
{
- ssize_t n = ctx->io->readfnc (ctx, buf, nleft);
+ ssize_t n = ctx->engine.readfnc (ctx, buf, nleft);
if (n < 0)
{
@@ -249,7 +249,7 @@ assuan_read_line (assuan_context_t ctx, char **line, size_t *linelen)
{
err = _assuan_read_line (ctx);
}
- while (_assuan_error_is_eagain (err));
+ while (_assuan_error_is_eagain (ctx, err));
*line = ctx->inbound.line;
*linelen = ctx->inbound.linelen;
@@ -551,19 +551,19 @@ assuan_sendfd (assuan_context_t ctx, assuan_fd_t fd)
return _assuan_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
#endif
- if (! ctx->io->sendfd)
+ if (! ctx->engine.sendfd)
return set_error (ctx, GPG_ERR_NOT_IMPLEMENTED,
"server does not support sending and receiving "
"of file descriptors");
- return ctx->io->sendfd (ctx, fd);
+ return ctx->engine.sendfd (ctx, fd);
}
gpg_error_t
assuan_receivefd (assuan_context_t ctx, assuan_fd_t *fd)
{
- if (! ctx->io->receivefd)
+ if (! ctx->engine.receivefd)
return set_error (ctx, GPG_ERR_NOT_IMPLEMENTED,
"server does not support sending and receiving "
"of file descriptors");
- return ctx->io->receivefd (ctx, fd);
+ return ctx->engine.receivefd (ctx, fd);
}
diff --git a/src/assuan-client.c b/src/assuan-client.c
index aa74f81..1f860b8 100644
--- a/src/assuan-client.c
+++ b/src/assuan-client.c
@@ -49,7 +49,7 @@ _assuan_read_from_server (assuan_context_t ctx, int *okay, int *off)
{
rc = _assuan_read_line (ctx);
}
- while (_assuan_error_is_eagain (rc));
+ while (_assuan_error_is_eagain (ctx, rc));
if (rc)
return rc;
line = ctx->inbound.line;
diff --git a/src/assuan-defs.h b/src/assuan-defs.h
index 95706d6..38f51ed 100644
--- a/src/assuan-defs.h
+++ b/src/assuan-defs.h
@@ -56,19 +56,6 @@ struct cmdtbl_s
};
-/* A structure to dispatch I/O functions. */
-struct assuan_io
-{
- /* Routine to read from input_fd. Sets errno on failure. */
- ssize_t (*readfnc) (assuan_context_t, void *, size_t);
- /* Routine to write to output_fd. Sets errno on failure. */
- ssize_t (*writefnc) (assuan_context_t, const void *, size_t);
- /* Send a file descriptor. */
- gpg_error_t (*sendfd) (assuan_context_t, assuan_fd_t);
- /* Receive a file descriptor. */
- gpg_error_t (*receivefd) (assuan_context_t, assuan_fd_t *);
-};
-
/* The context we use with most functions. */
struct assuan_context_s
@@ -97,17 +84,30 @@ struct assuan_context_s
{
unsigned int no_waitpid : 1;
unsigned int confidential : 1;
+ unsigned int no_fixsignals : 1;
} flags;
/* If set, this is called right before logging an I/O line. */
assuan_io_monitor_t io_monitor;
void *io_monitor_data;
+ /* Callback handlers replacing system I/O functions. */
+ struct assuan_system_hooks system;
+
/* Now come the members specific to subsystems or engines. FIXME:
This is not developed yet. See below for the legacy members. */
struct
{
void (*release) (assuan_context_t ctx);
+
+ /* Routine to read from input_fd. Sets errno on failure. */
+ ssize_t (*readfnc) (assuan_context_t, void *, size_t);
+ /* Routine to write to output_fd. Sets errno on failure. */
+ ssize_t (*writefnc) (assuan_context_t, const void *, size_t);
+ /* Send a file descriptor. */
+ gpg_error_t (*sendfd) (assuan_context_t, assuan_fd_t);
+ /* Receive a file descriptor. */
+ gpg_error_t (*receivefd) (assuan_context_t, assuan_fd_t *);
} engine;
@@ -220,11 +220,6 @@ struct assuan_context_s
assuan_fd_t input_fd; /* Set by the INPUT command. */
assuan_fd_t output_fd; /* Set by the OUTPUT command. */
-
- /* io routines. */
- struct assuan_io *io;
-
-
};
@@ -242,6 +237,38 @@ void *_assuan_realloc (assuan_context_t ctx, void *ptr, size_t cnt);
void *_assuan_calloc (assuan_context_t ctx, size_t cnt, size_t elsize);
void _assuan_free (assuan_context_t ctx, void *ptr);
+/* System hooks. */
+void _assuan_usleep (assuan_context_t ctx, unsigned int usec);
+int _assuan_pipe (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx);
+int _assuan_close (assuan_context_t ctx, assuan_fd_t fd);
+ssize_t _assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer,
+ size_t size);
+ssize_t _assuan_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer,
+ size_t size);
+int _assuan_recvmsg (assuan_context_t ctx, assuan_fd_t fd,
+ assuan_msghdr_t msg, int flags);
+int _assuan_sendmsg (assuan_context_t ctx, assuan_fd_t fd,
+ assuan_msghdr_t msg, int flags);
+int _assuan_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);
+pid_t _assuan_waitpid (assuan_context_t ctx, pid_t pid, int nowait,
+ int *status, int options);
+int _assuan_socketpair (assuan_context_t ctx, int namespace, int style,
+ int protocol, int filedes[2]);
+
+extern struct assuan_system_hooks _assuan_system_hooks;
+
+/* Copy the system hooks struct, paying attention to version
+ differences. SRC is usually from the user, DST MUST be from the
+ library. */
+void
+_assuan_system_hooks_copy (assuan_system_hooks_t dst,
+ assuan_system_hooks_t src);
+
/*-- assuan-pipe-server.c --*/
void _assuan_release_context (assuan_context_t ctx);
@@ -273,7 +300,7 @@ gpg_error_t _assuan_inquire_ext_cb (assuan_context_t ctx);
void _assuan_inquire_release (assuan_context_t ctx);
/* Check if ERR means EAGAIN. */
-int _assuan_error_is_eagain (gpg_error_t err);
+int _assuan_error_is_eagain (assuan_context_t ctx, gpg_error_t err);
@@ -290,33 +317,22 @@ void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length);
/*-- assuan-io.c --*/
-pid_t _assuan_waitpid (pid_t pid, int *status, int options);
-
ssize_t _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size);
ssize_t _assuan_simple_write (assuan_context_t ctx, const void *buffer,
size_t size);
-ssize_t _assuan_io_read (assuan_fd_t fd, void *buffer, size_t size);
-ssize_t _assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size);
-#ifdef HAVE_W32_SYSTEM
-int _assuan_simple_sendmsg (assuan_context_t ctx, void *msg);
-int _assuan_simple_recvmsg (assuan_context_t ctx, void *msg);
-#else
-ssize_t _assuan_simple_sendmsg (assuan_context_t ctx, struct msghdr *msg);
-ssize_t _assuan_simple_recvmsg (assuan_context_t ctx, struct msghdr *msg);
-#endif
-
-void _assuan_usleep (unsigned int usec);
-
/*-- assuan-socket.c --*/
-int _assuan_close (assuan_fd_t fd);
-assuan_fd_t _assuan_sock_new (int domain, int type, int proto);
-int _assuan_sock_connect (assuan_fd_t sockfd,
+
+assuan_fd_t _assuan_sock_new (assuan_context_t ctx, int domain, int type,
+ int proto);
+int _assuan_sock_connect (assuan_context_t ctx, assuan_fd_t sockfd,
struct sockaddr *addr, int addrlen);
-int _assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen);
-int _assuan_sock_get_nonce (struct sockaddr *addr, int addrlen,
- assuan_sock_nonce_t *nonce);
-int _assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce);
+int _assuan_sock_bind (assuan_context_t ctx, assuan_fd_t sockfd,
+ struct sockaddr *addr, int addrlen);
+int _assuan_sock_get_nonce (assuan_context_t ctx, struct sockaddr *addr,
+ int addrlen, assuan_sock_nonce_t *nonce);
+int _assuan_sock_check_nonce (assuan_context_t ctx, assuan_fd_t fd,
+ assuan_sock_nonce_t *nonce);
#ifdef HAVE_W32_SYSTEM
int _assuan_sock_wsa2errno (int err);
#endif
diff --git a/src/assuan-error.c b/src/assuan-error.c
index 60cb0d3..c45ca67 100644
--- a/src/assuan-error.c
+++ b/src/assuan-error.c
@@ -33,13 +33,13 @@
/* A small helper function to treat EAGAIN transparently to the
caller. */
int
-_assuan_error_is_eagain (gpg_error_t err)
+_assuan_error_is_eagain (assuan_context_t ctx, gpg_error_t err)
{
if (gpg_err_code (err) == GPG_ERR_EAGAIN)
{
/* Avoid spinning by sleeping for one tenth of a second. */
- _assuan_usleep (100000);
- return 1;
+ _assuan_usleep (ctx, 100000);
+ return 1;
}
else
return 0;
diff --git a/src/assuan-handler.c b/src/assuan-handler.c
index fd41719..7291acd 100644
--- a/src/assuan-handler.c
+++ b/src/assuan-handler.c
@@ -219,6 +219,7 @@ std_handler_input (assuan_context_t ctx, char *line)
return PROCESS_DONE (ctx, 0);
}
+
/* Format is OUTPUT FD=<n> */
static gpg_error_t
std_handler_output (assuan_context_t ctx, char *line)
@@ -236,9 +237,6 @@ std_handler_output (assuan_context_t ctx, char *line)
}
-
-
-
/* This is a table with the standard commands and handler for them.
The table is used to initialize a new context and associate strings
with default handlers */
@@ -592,7 +590,7 @@ process_next (assuan_context_t ctx)
required to write full lines without blocking long after starting
a partial line. */
rc = _assuan_read_line (ctx);
- if (_assuan_error_is_eagain (rc))
+ if (_assuan_error_is_eagain (ctx, rc))
return 0;
if (rc)
return rc;
@@ -670,7 +668,7 @@ process_request (assuan_context_t ctx)
{
rc = _assuan_read_line (ctx);
}
- while (_assuan_error_is_eagain (rc));
+ while (_assuan_error_is_eagain (ctx, rc));
if (rc)
return rc;
if (*ctx->inbound.line == '#' || !ctx->inbound.linelen)
diff --git a/src/assuan-inquire.c b/src/assuan-inquire.c
index dba7cb1..8772a15 100644
--- a/src/assuan-inquire.c
+++ b/src/assuan-inquire.c
@@ -176,7 +176,7 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,
{
do
rc = _assuan_read_line (ctx);
- while (_assuan_error_is_eagain (rc));
+ while (_assuan_error_is_eagain (ctx, rc));
if (rc)
goto leave;
line = (unsigned char *) ctx->inbound.line;
diff --git a/src/assuan-io-pth.c b/src/assuan-io-pth.c
deleted file mode 100644
index 7e438e9..0000000
--- a/src/assuan-io-pth.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/* assuan-io-pth.c - Pth version of assua-io.c.
- Copyright (C) 2002, 2004, 2006-2009 Free Software Foundation, Inc.
-
- This file is part of Assuan.
-
- Assuan is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
-
- Assuan is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <sys/time.h>
-#include <sys/types.h>
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#if HAVE_SYS_UIO_H
-# include <sys/uio.h>
-#endif
-#include <unistd.h>
-#include <errno.h>
-#ifdef HAVE_W32_SYSTEM
-# include <windows.h>
-#else
-# include <sys/wait.h>
-#endif
-#include <pth.h>
-
-#include "assuan-defs.h"
-
-
-
-#ifndef HAVE_W32_SYSTEM
-pid_t
-_assuan_waitpid (pid_t pid, int *status, int options)
-{
- return pth_waitpid (pid, status, options);
-}
-#endif
-
-
-ssize_t
-_assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size)
-{
- /* Fixme: For W32 we should better not cast the HANDLE type to int.
- However, this requires changes in w32pth too. */
- return _assuan_io_read (ctx->inbound.fd, buffer, size);
-}
-
-ssize_t
-_assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size)
-{
- return _assuan_io_write (ctx->outbound.fd, buffer, size);
-}
-
-ssize_t
-_assuan_io_read (assuan_fd_t fd, void *buffer, size_t size)
-{
- return pth_read ((int)fd, buffer, size);
-}
-
-ssize_t
-_assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size)
-{
- return pth_write ((int)fd, buffer, size);
-}
-
-
-#ifdef HAVE_W32_SYSTEM
-int
-_assuan_simple_sendmsg (assuan_context_t ctx, void *msg)
-#else
-ssize_t
-_assuan_simple_sendmsg (assuan_context_t ctx, struct msghdr *msg)
-#endif
-{
-#if defined(HAVE_W32_SYSTEM)
- errno = ENOSYS;
- return -1;
-#else
- /* Pth does not provide a sendmsg function. Thus we implement it here. */
- int ret;
- int fd = ctx->outbound.fd;
- int fdmode;
-
- fdmode = pth_fdmode (fd, PTH_FDMODE_POLL);
- if (fdmode == PTH_FDMODE_ERROR)
- {
- errno = EBADF;
- return -1;
- }
- if (fdmode == PTH_FDMODE_BLOCK)
- {
- fd_set fds;
-
- FD_ZERO (&fds);
- FD_SET (fd, &fds);
- while ( (ret = pth_select (fd+1, NULL, &fds, NULL, NULL)) < 0
- && errno == EINTR)
- ;
- if (ret < 0)
- return -1;
- }
-
- while ((ret = sendmsg (fd, msg, 0)) == -1 && errno == EINTR)
- ;
- return ret;
-#endif
-}
-
-#ifdef HAVE_W32_SYSTEM
-int
-_assuan_simple_recvmsg (assuan_context_t ctx, void *msg)
-#else
-ssize_t
-_assuan_simple_recvmsg (assuan_context_t ctx, struct msghdr *msg)
-#endif
-{
-#if defined(HAVE_W32_SYSTEM)
- errno = ENOSYS;
- return -1;
-#else
- /* Pth does not provide a recvmsg function. Thus we implement it here. */
- int ret;
- int fd = ctx->inbound.fd;
- int fdmode;
-
- fdmode = pth_fdmode (fd, PTH_FDMODE_POLL);
- if (fdmode == PTH_FDMODE_ERROR)
- {
- errno = EBADF;
- return -1;
- }
- if (fdmode == PTH_FDMODE_BLOCK)
- {
- fd_set fds;
-
- FD_ZERO (&fds);
- FD_SET (fd, &fds);
- while ( (ret = pth_select (fd+1, &fds, NULL, NULL, NULL)) < 0
- && errno == EINTR)
- ;
- if (ret < 0)
- return -1;
- }
-
- while ((ret = recvmsg (fd, msg, 0)) == -1 && errno == EINTR)
- ;
- return ret;
-#endif
-}
-
-
-void
-_assuan_usleep (unsigned int usec)
-{
- pth_usleep (usec);
-}
diff --git a/src/assuan-io.c b/src/assuan-io.c
index 88accc3..c5bbc99 100644
--- a/src/assuan-io.c
+++ b/src/assuan-io.c
@@ -38,185 +38,15 @@
#include "assuan-defs.h"
-#ifndef HAVE_W32_SYSTEM
-pid_t
-_assuan_waitpid (pid_t pid, int *status, int options)
-{
- return waitpid (pid, status, options);
-}
-#endif
-
-
-static ssize_t
-do_io_read (assuan_fd_t fd, void *buffer, size_t size)
-{
-#ifdef HAVE_W32_SYSTEM
- /* Due to the peculiarities of the W32 API we can't use read for a
- network socket and thus we try to use recv first and fallback to
- read if recv detects that it is not a network socket. */
- int n;
-
- n = recv (HANDLE2SOCKET(fd), buffer, size, 0);
- if (n == -1)
- {
- switch (WSAGetLastError ())
- {
- case WSAENOTSOCK:
- {
- DWORD nread = 0;
-
- n = ReadFile (fd, buffer, size, &nread, NULL);
- if (!n)
- {
- switch (GetLastError())
- {
- case ERROR_BROKEN_PIPE: errno = EPIPE; break;
- default: errno = EIO;
- }
- n = -1;
- }
- else
- n = (int)nread;
- }
- break;
-
- case WSAEWOULDBLOCK: errno = EAGAIN; break;
- case ERROR_BROKEN_PIPE: errno = EPIPE; break;
- default: errno = EIO; break;
- }
- }
- return n;
-#else /*!HAVE_W32_SYSTEM*/
- return read (fd, buffer, size);
-#endif /*!HAVE_W32_SYSTEM*/
-}
-
-
-ssize_t
-_assuan_io_read (assuan_fd_t fd, void *buffer, size_t size)
-{
- return do_io_read (fd, buffer, size);
-}
-
ssize_t
_assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size)
{
- return do_io_read (ctx->inbound.fd, buffer, size);
+ return _assuan_read (ctx, ctx->inbound.fd, buffer, size);
}
-
-static ssize_t
-do_io_write (assuan_fd_t fd, const void *buffer, size_t size)
-{
-#ifdef HAVE_W32_SYSTEM
- /* Due to the peculiarities of the W32 API we can't use write for a
- network socket and thus we try to use send first and fallback to
- write if send detects that it is not a network socket. */
- int n;
-
- n = send (HANDLE2SOCKET(fd), buffer, size, 0);
- if (n == -1 && WSAGetLastError () == WSAENOTSOCK)
- {
- DWORD nwrite;
-
- n = WriteFile (fd, buffer, size, &nwrite, NULL);
- if (!n)
- {
- switch (GetLastError ())
- {
- case ERROR_BROKEN_PIPE:
- case ERROR_NO_DATA: errno = EPIPE; break;
- default: errno = EIO; break;
- }
- n = -1;
- }
- else
- n = (int)nwrite;
- }
- return n;
-#else /*!HAVE_W32_SYSTEM*/
- return write (fd, buffer, size);
-#endif /*!HAVE_W32_SYSTEM*/
-}
-
-ssize_t
-_assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size)
-{
- return do_io_write (fd, buffer, size);
-}
-
ssize_t
_assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size)
{
- return do_io_write (ctx->outbound.fd, buffer, size);
+ return _assuan_write (ctx, ctx->outbound.fd, buffer, size);
}
-
-
-#ifdef HAVE_W32_SYSTEM
-int
-_assuan_simple_sendmsg (assuan_context_t ctx, void *msg)
-#else
-ssize_t
-_assuan_simple_sendmsg (assuan_context_t ctx, struct msghdr *msg)
-#endif
-{
-#ifdef HAVE_W32_SYSTEM
- errno = ENOSYS;
- return -1;
-#else
- int ret;
- while ( (ret = sendmsg (ctx->outbound.fd, msg, 0)) == -1 && errno == EINTR)
- ;
- return ret;
-#endif
-}
-
-
-#ifdef HAVE_W32_SYSTEM
-int
-_assuan_simple_recvmsg (assuan_context_t ctx, void *msg)
-#else
-ssize_t
-_assuan_simple_recvmsg (assuan_context_t ctx, struct msghdr *msg)
-#endif
-{
-#ifdef HAVE_W32_SYSTEM
- errno = ENOSYS;
- return -1;
-#else
- int ret;
- while ( (ret = recvmsg (ctx->inbound.fd, msg, 0)) == -1 && errno == EINTR)
- ;
- return ret;
-#endif
-}
-
-
-void
-_assuan_usleep (unsigned int usec)
-{
- if (usec)
- {
-#ifdef HAVE_NANOSLEEP
- struct timespec req;
- struct timespec rem;
-
- req.tv_sec = 0;
- req.tv_nsec = usec * 1000;
-
- while (nanosleep (&req, &rem) < 0 && errno == EINTR)
- req = rem;
-
-#elif defined(HAVE_W32_SYSTEM)
- Sleep (usec / 1000);
-#else
- struct timeval tv;
-
- tv.tv_sec = usec / 1000000;
- tv.tv_usec = usec % 1000000;
- select (0, NULL, NULL, NULL, &tv);
-#endif
- }
-}
-
diff --git a/src/assuan-listen.c b/src/assuan-listen.c
index 3f57922..2f6c8a3 100644
--- a/src/assuan-listen.c
+++ b/src/assuan-listen.c
@@ -138,7 +138,7 @@ assuan_close_input_fd (assuan_context_t ctx)
{
if (!ctx || ctx->input_fd == ASSUAN_INVALID_FD)
return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
- _assuan_close (ctx->input_fd);
+ _assuan_close (ctx, ctx->input_fd);
ctx->input_fd = ASSUAN_INVALID_FD;
return 0;
}
@@ -151,7 +151,7 @@ assuan_close_output_fd (assuan_context_t ctx)
if (!ctx || ctx->output_fd == ASSUAN_INVALID_FD)
return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
- _assuan_close (ctx->output_fd);
+ _assuan_close (ctx, ctx->output_fd);
ctx->output_fd = ASSUAN_INVALID_FD;
return 0;
}
diff --git a/src/assuan-pipe-connect.c b/src/assuan-pipe-connect.c
index c5e20e7..bdc59a4 100644
--- a/src/assuan-pipe-connect.c
+++ b/src/assuan-pipe-connect.c
@@ -62,7 +62,6 @@
static void
fix_signals (void)
{
-#ifndef _ASSUAN_NO_FIXED_SIGNALS
#ifndef HAVE_DOSISH_SYSTEM /* No SIGPIPE for these systems. */
static int fixed_signals;
@@ -82,58 +81,28 @@ fix_signals (void)
/* FIXME: This is not MT safe */
}
#endif /*HAVE_DOSISH_SYSTEM*/
-#endif /*!_ASSUAN_NO_FIXED_SIGNALS*/
}
-#ifndef HAVE_W32_SYSTEM
-static int
-writen (int fd, const char *buffer, size_t length)
-{
- while (length)
- {
- int nwritten = write (fd, buffer, length);
-
- if (nwritten < 0)
- {
- if (errno == EINTR)
- continue;
- return -1; /* write error */
- }
- length -= nwritten;
- buffer += nwritten;
- }
- return 0; /* okay */
-}
-#endif
-
static void
do_finish (assuan_context_t ctx)
{
if (ctx->inbound.fd != ASSUAN_INVALID_FD)
{
- _assuan_close (ctx->inbound.fd);
+ _assuan_close (ctx, ctx->inbound.fd);
if (ctx->inbound.fd == ctx->outbound.fd)
ctx->outbound.fd = ASSUAN_INVALID_FD;
ctx->inbound.fd = ASSUAN_INVALID_FD;
}
if (ctx->outbound.fd != ASSUAN_INVALID_FD)
{
- _assuan_close (ctx->outbound.fd);
+ _assuan_close (ctx, ctx->outbound.fd);
ctx->outbound.fd = ASSUAN_INVALID_FD;
}
- if (ctx->pid != (pid_t)(-1) && ctx->pid)
+ if (ctx->pid != ASSUAN_INVALID_PID && ctx->pid)
{
-#ifndef HAVE_W32_SYSTEM
-#ifndef _ASSUAN_USE_DOUBLE_FORK
- if (!ctx->flags.no_waitpid)
- _assuan_waitpid (ctx->pid, NULL, 0);
- ctx->pid =(pid_t)(-1);
-#endif
-#else /*!HAVE_W32_SYSTEM*/
- CloseHandle ((HANDLE) ctx->pid);
- ctx->pid = (pid_t) INVALID_HANDLE_VALUE;
-#endif /*HAVE_W32_SYSTEM*/
+ _assuan_waitpid (ctx, ctx->pid, ctx->flags.no_waitpid, NULL, 0);
+ ctx->pid = ASSUAN_INVALID_PID;
}
}
@@ -166,178 +135,96 @@ initial_handshake (assuan_context_t ctx)
return err;
}
+
+struct at_pipe_fork
+{
+ void (*user_atfork) (void *opaque, int reserved);
+ void *user_atforkvalue;
+};
+
+
+static void
+at_pipe_fork_cb (void *opaque, int reserved)
+{
+ struct at_pipe_fork *atp = opaque;
+
+ if (atp->user_atfork)
+ atp->user_atfork (atp->user_atforkvalue, reserved);
#ifndef HAVE_W32_SYSTEM
-#define pipe_connect pipe_connect_unix
-/* Unix version of the pipe connection code. We use an extra macro to
- make ChangeLog entries easier. */
+ {
+ char mypidstr[50];
+
+ /* We store our parents pid in the environment so that the execed
+ assuan server is able to read the actual pid of the client.
+ The server can't use getppid because it might have been double
+ forked before the assuan server has been initialized. */
+ sprintf (mypidstr, "%lu", (unsigned long) getpid ());
+ setenv ("_assuan_pipe_connect_pid", mypidstr, 1);
+
+ /* Make sure that we never pass a connection fd variable when
+ using a simple pipe. */
+ unsetenv ("_assuan_connection_fd");
+ }
+#endif
+}
+
+
static gpg_error_t
-pipe_connect_unix (assuan_context_t ctx,
- const char *name, const char *const argv[],
- int *fd_child_list,
- void (*atfork) (void *opaque, int reserved),
- void *atforkvalue, unsigned int flags)
+pipe_connect (assuan_context_t ctx,
+ const char *name, const char **argv,
+ int *fd_child_list,
+ void (*atfork) (void *opaque, int reserved),
+ void *atforkvalue, unsigned int flags)
{
- int rp[2];
- int wp[2];
- pid_t pid;
- char mypidstr[50];
gpg_error_t rc;
- static struct assuan_io io = { _assuan_simple_read, _assuan_simple_write,
- 0, 0 };
+ assuan_fd_t rp[2];
+ assuan_fd_t wp[2];
+ pid_t pid;
+ int res;
+ struct at_pipe_fork atp;
- (void)flags;
+ atp.user_atfork = atfork;
+ atp.user_atforkvalue = atforkvalue;
if (!ctx || !name || !argv || !argv[0])
return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
- fix_signals ();
+ if (! ctx->flags.no_fixsignals)
+ fix_signals ();
- sprintf (mypidstr, "%lu", (unsigned long)getpid ());
-
- if (pipe (rp) < 0)
- return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);
+ if (_assuan_pipe (ctx, rp, 1) < 0)
+ return _assuan_error (ctx, gpg_err_code_from_syserror ());
- if (pipe (wp) < 0)
+ if (_assuan_pipe (ctx, wp, 0) < 0)
{
- close (rp[0]);
- close (rp[1]);
- return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);
+ _assuan_close (ctx, rp[0]);
+ _assuan_close (ctx, rp[1]);
+ return _assuan_error (ctx, gpg_err_code_from_syserror ());
}
- /* FIXME: For GPGME we should better use _gpgme_io_spawn. The PID
- stored here is actually soon useless. */
- pid = fork ();
- if (pid < 0)
+ /* FIXME: Use atfork handler that closes child fds on Unix. */
+ res = _assuan_spawn (ctx, &pid, name, argv, wp[0], rp[1],
+ fd_child_list, at_pipe_fork_cb, &atp, flags);
+ if (res < 0)
{
- close (rp[0]);
- close (rp[1]);
- close (wp[0]);
- close (wp[1]);
- return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);
+ rc = gpg_err_code_from_syserror ();
+ _assuan_close (ctx, rp[0]);
+ _assuan_close (ctx, rp[1]);
+ _assuan_close (ctx, wp[0]);
+ _assuan_close (ctx, wp[1]);
+ return _assuan_error (ctx, rc);
}
- if (pid == 0)
- {
-#ifdef _ASSUAN_USE_DOUBLE_FORK
- pid_t pid2;
-
- if ((pid2 = fork ()) == 0)
-#endif
- {
- int i, n;
- char errbuf[512];
- int *fdp;
-
- if (atfork)
- atfork (atforkvalue, 0);
-
- /* Dup handles to stdin/stdout. */
- if (rp[1] != STDOUT_FILENO)
- {
- if (dup2 (rp[1], STDOUT_FILENO) == -1)
- {
- TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_unix", ctx,
- "dup2 failed in child: %s", strerror (errno));
- _exit (4);
- }
- }
- if (wp[0] != STDIN_FILENO)
- {
- if (dup2 (wp[0], STDIN_FILENO) == -1)
- {
- TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_unix", ctx,
- "dup2 failed in child: %s", strerror (errno));
- _exit (4);
- }
- }
-
- /* Dup stderr to /dev/null unless it is in the list of FDs to be
- passed to the child. */
- fdp = fd_child_list;
- if (fdp)
- {
- for (; *fdp != -1 && *fdp != STDERR_FILENO; fdp++)
- ;
- }
- if (!fdp || *fdp == -1)
- {
- int fd = open ("/dev/null", O_WRONLY);
- if (fd == -1)
- {
- TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_unix", ctx,
- "can't open `/dev/null': %s", strerror (errno));
- _exit (4);
- }
- if (dup2 (fd, STDERR_FILENO) == -1)
- {
- TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_unix", ctx,
- "dup2(dev/null, 2) failed: %s", strerror (errno));
- _exit (4);
- }
- }
-
-
- /* Close all files which will not be duped and are not in the
- fd_child_list. */
- n = sysconf (_SC_OPEN_MAX);
- if (n < 0)
- n = MAX_OPEN_FDS;
- for (i=0; i < n; i++)
- {
- if ( i == STDIN_FILENO || i == STDOUT_FILENO
- || i == STDERR_FILENO)
- continue;
- fdp = fd_child_list;
- if (fdp)
- {
- while (*fdp != -1 && *fdp != i)
- fdp++;
- }
-
- if (!(fdp && *fdp != -1))
- close(i);
- }
- errno = 0;
-
- /* We store our parents pid in the environment so that the
- execed assuan server is able to read the actual pid of the
- client. The server can't use getppid because it might have
- been double forked before the assuan server has been
- initialized. */
- setenv ("_assuan_pipe_connect_pid", mypidstr, 1);
-
- /* Make sure that we never pass a connection fd variable
- when using a simple pipe. */
- unsetenv ("_assuan_connection_fd");
-
- execv (name, (char *const *) argv);
- /* oops - use the pipe to tell the parent about it */
- snprintf (errbuf, sizeof(errbuf)-1,
- "ERR %d can't exec `%s': %.50s\n",
- _assuan_error (ctx, GPG_ERR_ASS_SERVER_START),
- name, strerror (errno));
- errbuf[sizeof(errbuf)-1] = 0;
- writen (1, errbuf, strlen (errbuf));
- _exit (4);
- }
-#ifdef _ASSUAN_USE_DOUBLE_FORK
- if (pid2 == -1)
- _exit (1);
- else
- _exit (0);
-#endif
- }
-
-#ifdef _ASSUAN_USE_DOUBLE_FORK
- _assuan_waitpid (pid, NULL, 0);
- pid = -1;
-#endif
-
- close (rp[1]);
- close (wp[0]);
+ /* Close the stdin/stdout child fds in the parent. */
+ _assuan_close (ctx, rp[1]);
+ _assuan_close (ctx, wp[0]);
- ctx->io = &io;
+ ctx->engine.release = _assuan_disconnect;
+ ctx->engine.readfnc = _assuan_simple_read;
+ ctx->engine.writefnc = _assuan_simple_write;
+ ctx->engine.sendfd = NULL;
+ ctx->engine.receivefd = NULL;
ctx->pipe_mode = 1;
ctx->inbound.fd = rp[0]; /* Our inbound is read end of read pipe. */
ctx->outbound.fd = wp[1]; /* Our outbound is write end of write pipe. */
@@ -350,176 +237,133 @@ pipe_connect_unix (assuan_context_t ctx,
_assuan_reset (ctx);
return rc;
}
-#endif /*!HAVE_W32_SYSTEM*/
+/* FIXME: For socketpair_connect, use spawn function and add atfork
+ handler to do the right thing. Instead of stdin and stdout, we
+ extend the fd_child_list by fds[1]. */
+
+#ifndef HAVE_W32_SYSTEM
+struct at_socketpair_fork
+{
+ assuan_fd_t peer_fd;
+ void (*user_atfork) (void *opaque, int reserved);
+ void *user_atforkvalue;
+};
+
+
+static void
+at_socketpair_fork_cb (void *opaque, int reserved)
+{
+ struct at_socketpair_fork *atp = opaque;
+
+ if (atp->user_atfork)
+ atp->user_atfork (atp->user_atforkvalue, reserved);
+
#ifndef HAVE_W32_SYSTEM
+ {
+ char mypidstr[50];
+
+ /* We store our parents pid in the environment so that the execed
+ assuan server is able to read the actual pid of the client.
+ The server can't use getppid because it might have been double
+ forked before the assuan server has been initialized. */
+ sprintf (mypidstr, "%lu", (unsigned long) getpid ());
+ setenv ("_assuan_pipe_connect_pid", mypidstr, 1);
+
+ /* Now set the environment variable used to convey the
+ connection's file descriptor. */
+ sprintf (mypidstr, "%d", atp->peer_fd);
+ if (setenv ("_assuan_connection_fd", mypidstr, 1))
+ _exit (4);
+ }
+#endif
+}
+
+
/* This function is similar to pipe_connect but uses a socketpair and
sets the I/O up to use sendmsg/recvmsg. */
static gpg_error_t
socketpair_connect (assuan_context_t ctx,
- const char *name, const char *argv[],
+ const char *name, const char **argv,
int *fd_child_list,
void (*atfork) (void *opaque, int reserved),
void *atforkvalue)
{
gpg_error_t err;
+ int idx;
int fds[2];
char mypidstr[50];
pid_t pid;
+ int *child_fds = NULL;
+ int child_fds_cnt = 0;
+ struct at_socketpair_fork atp;
+ int rc;
+
+ TRACE_BEG3 (ctx, ASSUAN_LOG_CTX, "socketpair_connect", ctx,
+ "name=%s,atfork=%p,atforkvalue=%p", name ? name : "(null)",
+ atfork, atforkvalue);
+
+ atp.user_atfork = atfork;
+ atp.user_atforkvalue = atforkvalue;
if (!ctx
|| (name && (!argv || !argv[0]))
|| (!name && !argv))
return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
- fix_signals ();
+ if (! ctx->flags.no_fixsignals)
+ fix_signals ();
sprintf (mypidstr, "%lu", (unsigned long)getpid ());
- if ( socketpair (AF_LOCAL, SOCK_STREAM, 0, fds) )
+ while (fd_child_list[child_fds_cnt] != ASSUAN_INVALID_FD)
+ child_fds_cnt++;
+ child_fds = _assuan_malloc (ctx, (child_fds_cnt + 2) * sizeof (int));
+ if (! child_fds)
+ return TRACE_ERR (gpg_err_code_from_syserror ());
+ memcpy (&child_fds[1], fd_child_list, (child_fds_cnt + 1) * sizeof (int));
+
+ if (_assuan_socketpair (ctx, AF_LOCAL, SOCK_STREAM, 0, fds))
{
- TRACE1 (ctx, ASSUAN_LOG_SYSIO, "socketpair_connect", ctx,
- "socketpair failed: %s", strerror (errno));
- return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);
+ TRACE_LOG1 ("socketpair failed: %s", strerror (errno));
+ _assuan_free (ctx, child_fds);
+ return TRACE_ERR (GPG_ERR_ASS_GENERAL);
}
+ atp.peer_fd = fds[1];
+ child_fds[0] = fds[1];
- pid = fork ();
- if (pid < 0)
+
+ rc = _assuan_spawn (ctx, &pid, name, argv, ASSUAN_INVALID_FD,
+ ASSUAN_INVALID_FD, child_fds, at_socketpair_fork_cb,
+ &atp, 0);
+ if (rc < 0)
{
- close (fds[0]);
- close (fds[1]);
- /* FIXME: cleanup ctx */
- return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);
+ err = gpg_err_code_from_syserror ();
+ _assuan_close (ctx, fds[0]);
+ _assuan_close (ctx, fds[1]);
+ _assuan_free (ctx, child_fds);
+ return TRACE_ERR (err);
}
- if (pid == 0)
+ /* For W32, the user needs to know the server-local names of the
+ inherited handles. Return them here. Note that the translation
+ of the peer socketpair fd (fd_child_list[0]) must be done by the
+ wrapper program based on the environment variable
+ _assuan_connection_fd. */
+ for (idx = 0; fd_child_list[idx] != -1; idx++)
+ /* We add 1 to skip over the socketpair end. */
+ fd_child_list[idx] = child_fds[idx + 1];
+
+ /* If this is the server child process, exit early. */
+ if (! name && (*argv)[0] == 's')
{
-#ifdef _ASSUAN_USE_DOUBLE_FORK
- pid_t pid2;
-
- if ((pid2 = fork ()) == 0)
-#endif
- {
- int fd, i, n;
- char errbuf[512];
- int *fdp;
-
- if (atfork)
- atfork (atforkvalue, 0);
-
- /* Connect stdin and stdout to /dev/null. */
- fd = open ("/dev/null", O_RDONLY);
- if (fd == -1 || dup2 (fd, STDIN_FILENO) == -1)
- {
- TRACE1 (ctx, ASSUAN_LOG_SYSIO, "socketpair_connect", ctx,
- "dup2(dev/null) failed: %s", strerror (errno));
- _exit (4);
- }
- fd = open ("/dev/null", O_WRONLY);
- if (fd == -1 || dup2 (fd, STDOUT_FILENO) == -1)
- {
- TRACE1 (ctx, ASSUAN_LOG_SYSIO, "socketpair_connect", ctx,
- "dup2(dev/null) failed: %s", strerror (errno));
- _exit (4);
- }
-
- /* Dup stderr to /dev/null unless it is in the list of FDs to be
- passed to the child. */
- fdp = fd_child_list;
- if (fdp)
- {
- for (; *fdp != -1 && *fdp != STDERR_FILENO; fdp++)
- ;
- }
- if (!fdp || *fdp == -1)
- {
- fd = open ("/dev/null", O_WRONLY);
- if (fd == -1 || dup2 (fd, STDERR_FILENO) == -1)
- {
- TRACE1 (ctx, ASSUAN_LOG_SYSIO, "socketpair_connect", ctx,
- "dup2(dev/null) failed: %s", strerror (errno));
- _exit (4);
- }
- }
-
-
- /* Close all files which will not be duped, are not in the
- fd_child_list and are not the connection fd. */
- n = sysconf (_SC_OPEN_MAX);
- if (n < 0)
- n = MAX_OPEN_FDS;
- for (i=0; i < n; i++)
- {
- if ( i == STDIN_FILENO || i == STDOUT_FILENO
- || i == STDERR_FILENO || i == fds[1])
- continue;
- fdp = fd_child_list;
- if (fdp)
- {
- while (*fdp != -1 && *fdp != i)
- fdp++;
- }
-
- if (!(fdp && *fdp != -1))
- close(i);
- }
- errno = 0;
-
- /* We store our parents pid in the environment so that the
- execed assuan server is able to read the actual pid of the
- client. The server can't use getppid becuase it might have
- been double forked before the assuan server has been
- initialized. */
- setenv ("_assuan_pipe_connect_pid", mypidstr, 1);
-
- /* Now set the environment variable used to convey the
- connection's file descriptor. */
- sprintf (mypidstr, "%d", fds[1]);
- if (setenv ("_assuan_connection_fd", mypidstr, 1))
- {
- TRACE1 (ctx, ASSUAN_LOG_SYSIO, "socketpair_connect", ctx,
- "setenv failed: %s", strerror (errno));
- _exit (4);
- }
-
- if (!name)
- {
- /* No name and no args given, thus we don't do an exec
- but continue the forked process. */
- *argv = "server";
-
- /* FIXME: Cleanup. */
- return 0;
- }
-
- execv (name, (char *const *) argv);
- /* oops - use the pipe to tell the parent about it */
- snprintf (errbuf, sizeof(errbuf)-1,
- "ERR %d can't exec `%s': %.50s\n",
- _assuan_error (ctx, GPG_ERR_ASS_SERVER_START),
- name, strerror (errno));
- errbuf[sizeof(errbuf)-1] = 0;
- writen (fds[1], errbuf, strlen (errbuf));
- _exit (4);
- }
-#ifdef _ASSUAN_USE_DOUBLE_FORK
- if (pid2 == -1)
- _exit (1);
- else
- _exit (0);
-#endif
+ _assuan_free (ctx, child_fds);
+ _assuan_close (ctx, fds[0]);
+ return 0;
}
- if (! name)
- *argv = "client";
-
-#ifdef _ASSUAN_USE_DOUBLE_FORK
- _assuan_waitpid (pid, NULL, 0);
- pid = -1;
-#endif
-
- close (fds[1]);
+ _assuan_close (ctx, fds[1]);
ctx->pipe_mode = 1;
ctx->inbound.fd = fds[0];
@@ -535,282 +379,6 @@ socketpair_connect (assuan_context_t ctx,
}
#endif /*!HAVE_W32_SYSTEM*/
-
-
-#ifdef HAVE_W32_SYSTEM
-/* Build a command line for use with W32's CreateProcess. On success
- CMDLINE gets the address of a newly allocated string. */
-static int
-build_w32_commandline (assuan_context_t ctx, const char * const *argv, char **cmdline)
-{
- int i, n;
- const char *s;
- char *buf, *p;
-
- *cmdline = NULL;
- n = 0;
- for (i=0; (s=argv[i]); i++)
- {
- n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */
- for (; *s; s++)
- if (*s == '\"')
- n++; /* Need to double inner quotes. */
- }
- n++;
-
- buf = p = _assuan_malloc (ctx, n);
- if (!buf)
- return -1;
-
- for (i=0; argv[i]; i++)
- {
- if (i)
- p = stpcpy (p, " ");
- if (!*argv[i]) /* Empty string. */
- p = stpcpy (p, "\"\"");
- else if (strpbrk (argv[i], " \t\n\v\f\""))
- {
- p = stpcpy (p, "\"");
- for (s=argv[i]; *s; s++)
- {
- *p++ = *s;
- if (*s == '\"')
- *p++ = *s;
- }
- *p++ = '\"';
- *p = 0;
- }
- else
- p = stpcpy (p, argv[i]);
- }
-
- *cmdline= buf;
- return 0;
-}
-#endif /*HAVE_W32_SYSTEM*/
-
-
-#ifdef HAVE_W32_SYSTEM
-/* Create pipe where one end end is inheritable. */
-static int
-create_inheritable_pipe (assuan_context_t ctx,
- assuan_fd_t filedes[2], int for_write)
-{
- HANDLE r, w, h;
- SECURITY_ATTRIBUTES sec_attr;
-
- memset (&sec_attr, 0, sizeof sec_attr );
- sec_attr.nLength = sizeof sec_attr;
- sec_attr.bInheritHandle = FALSE;
-
- if (!CreatePipe (&r, &w, &sec_attr, 0))
- {
- TRACE1 (ctx, ASSUAN_LOG_SYSIO, "create_inheritable_pipe", ctx,
- "CreatePipe failed: %s", _assuan_w32_strerror (ctx, -1));
- return -1;
- }
-
- if (!DuplicateHandle (GetCurrentProcess(), for_write? r : w,
- GetCurrentProcess(), &h, 0,
- TRUE, DUPLICATE_SAME_ACCESS ))
- {
- TRACE1 (ctx, ASSUAN_LOG_SYSIO, "create_inheritable_pipe", ctx,
- "DuplicateHandle failed: %s", _assuan_w32_strerror (ctx, -1));
- CloseHandle (r);
- CloseHandle (w);
- return -1;
- }
- if (for_write)
- {
- CloseHandle (r);
- r = h;
- }
- else
- {
- CloseHandle (w);
- w = h;
- }
-
- filedes[0] = r;
- filedes[1] = w;
- return 0;
-}
-#endif /*HAVE_W32_SYSTEM*/
-
-
-#ifdef HAVE_W32_SYSTEM
-#define pipe_connect pipe_connect_w32
-/* W32 version of the pipe connection code. */
-static gpg_error_t
-pipe_connect_w32 (assuan_context_t ctx,
- const char *name, const char *const argv[],
- int *fd_child_list,
- void (*atfork) (void *opaque, int reserved),
- void *atforkvalue, unsigned int flags)
-{
- gpg_error_t err;
- assuan_fd_t rp[2];
- assuan_fd_t wp[2];
- char mypidstr[50];
- char *cmdline;
- SECURITY_ATTRIBUTES sec_attr;
- PROCESS_INFORMATION pi =
- {
- NULL, /* Returns process handle. */
- 0, /* Returns primary thread handle. */
- 0, /* Returns pid. */
- 0 /* Returns tid. */
- };
- STARTUPINFO si;
- int fd, *fdp;
- HANDLE nullfd = INVALID_HANDLE_VALUE;
- static struct assuan_io io = { _assuan_simple_read, _assuan_simple_write,
- 0, 0 };
-
- if (!ctx || !name || !argv || !argv[0])
- return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
-
- fix_signals ();
-
- sprintf (mypidstr, "%lu", (unsigned long)getpid ());
-
- /* Build the command line. */
- if (build_w32_commandline (ctx, argv, &cmdline))
- return _assuan_error (ctx, gpg_err_code_from_syserror ());
-
- /* Create thew two pipes. */
- if (create_inheritable_pipe (ctx, rp, 0))
- {
- _assuan_free (ctx, cmdline);
- return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);
- }
-
- if (create_inheritable_pipe (ctx, wp, 1))
- {
- CloseHandle (rp[0]);
- CloseHandle (rp[1]);
- _assuan_free (ctx, cmdline);
- return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);
- }
-
-
- /* fixme: Actually we should set the "_assuan_pipe_connect_pid" env
- variable. However this requires us to write a full environment
- handler, because the strings are expected in sorted order. The
- suggestion given in the MS Reference Library, to save the old
- value, changeit, create proces and restore it, is not thread
- safe. */
-
- /* Start the process. */
- memset (&sec_attr, 0, sizeof sec_attr );
- sec_attr.nLength = sizeof sec_attr;
- sec_attr.bInheritHandle = FALSE;
-
- memset (&si, 0, sizeof si);
- si.cb = sizeof (si);
- si.dwFlags = STARTF_USESTDHANDLES;
- si.hStdInput = wp[0];
- si.hStdOutput = rp[1];
-
- /* Dup stderr to /dev/null unless it is in the list of FDs to be
- passed to the child. */
- fd = fileno (stderr);
- fdp = fd_child_list;
- if (fdp)
- {
- for (; *fdp != -1 && *fdp != fd; fdp++)
- ;
- }
- if (!fdp || *fdp == -1)
- {
- nullfd = CreateFile ("nul", GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL, OPEN_EXISTING, 0, NULL);
- if (nullfd == INVALID_HANDLE_VALUE)
- {
- TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_w32", ctx,
- "can't open `nul': %s", _assuan_w32_strerror (ctx, -1));
- CloseHandle (rp[0]);
- CloseHandle (rp[1]);
- CloseHandle (wp[0]);
- CloseHandle (wp[1]);
- _assuan_free (ctx, cmdline);
- /* FIXME: Cleanup? */
- return -1;
- }
- si.hStdError = nullfd;
- }
- else
- si.hStdError = (void*)_get_osfhandle (fd);
-
-
- /* Note: We inherit all handles flagged as inheritable. This seems
- to be a security flaw but there seems to be no way of selecting
- handles to inherit. */
- /* _assuan_log_printf ("CreateProcess, path=`%s' cmdline=`%s'\n", */
- /* name, cmdline); */
- if (!CreateProcess (name, /* Program to start. */
- cmdline, /* Command line arguments. */
- &sec_attr, /* Process security attributes. */
- &sec_attr, /* Thread security attributes. */
- TRUE, /* Inherit handles. */
- (CREATE_DEFAULT_ERROR_MODE
- | ((flags & 128)? DETACHED_PROCESS : 0)
- | GetPriorityClass (GetCurrentProcess ())
- | CREATE_SUSPENDED), /* Creation flags. */
- NULL, /* Environment. */
- NULL, /* Use current drive/directory. */
- &si, /* Startup information. */
- &pi /* Returns process information. */
- ))
- {
- TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_w32", ctx,
- "CreateProcess failed: %s", _assuan_w32_strerror (ctx, -1));
- CloseHandle (rp[0]);
- CloseHandle (rp[1]);
- CloseHandle (wp[0]);
- CloseHandle (wp[1]);
- if (nullfd != INVALID_HANDLE_VALUE)
- CloseHandle (nullfd);
- _assuan_free (ctx, cmdline);
- /* FIXME: Cleanup? */
- return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);
- }
- _assuan_free (ctx, cmdline);
- cmdline = NULL;
- if (nullfd != INVALID_HANDLE_VALUE)
- {
- CloseHandle (nullfd);
- nullfd = INVALID_HANDLE_VALUE;
- }
-
- CloseHandle (rp[1]);
- CloseHandle (wp[0]);
-
- /* _assuan_log_printf ("CreateProcess ready: hProcess=%p hThread=%p" */
- /* " dwProcessID=%d dwThreadId=%d\n", */
- /* pi.hProcess, pi.hThread, */
- /* (int) pi.dwProcessId, (int) pi.dwThreadId); */
-
- ResumeThread (pi.hThread);
- CloseHandle (pi.hThread);
-
- ctx->io = &io;
- ctx->engine.release = _assuan_disconnect;
- ctx->pipe_mode = 1;
- ctx->inbound.fd = rp[0]; /* Our inbound is read end of read pipe. */
- ctx->outbound.fd = wp[1]; /* Our outbound is write end of write pipe. */
- ctx->deinit_handler = do_deinit;
- ctx->finish_handler = do_finish;
- ctx->pid = (pid_t) pi.hProcess;
-
- err = initial_handshake (ctx);
- if (err)
- _assuan_reset (ctx);
- return err;
-}
-#endif /*HAVE_W32_SYSTEM*/
-
/* Connect to a server over a pipe, creating the assuan context and
returning it in CTX. The server filename is NAME, the argument
@@ -820,6 +388,9 @@ gpg_error_t
assuan_pipe_connect (assuan_context_t ctx, const char *name,
const char *argv[], int *fd_child_list)
{
+ TRACE1 (ctx, ASSUAN_LOG_CTX, "assuan_pipe_connect", ctx,
+ "name=%s", name ? name : "(null)");
+
return pipe_connect (ctx, name, argv, fd_child_list, NULL, NULL, 0);
}
@@ -860,6 +431,9 @@ assuan_pipe_connect_ext (assuan_context_t ctx,
void (*atfork) (void *opaque, int reserved),
void *atforkvalue, unsigned int flags)
{
+ TRACE2 (ctx, ASSUAN_LOG_CTX, "assuan_pipe_connect_ext", ctx,
+ "name=%s,flags=0x%x", name ? name : "(null)", flags);
+
if ((flags & 1))
{
#ifdef HAVE_W32_SYSTEM
@@ -873,3 +447,4 @@ assuan_pipe_connect_ext (assuan_context_t ctx,
return pipe_connect (ctx, name, argv, fd_child_list, atfork, atforkvalue,
flags);
}
+
diff --git a/src/assuan-pipe-server.c b/src/assuan-pipe-server.c
index 3c30d48..7849fa5 100644
--- a/src/assuan-pipe-server.c
+++ b/src/assuan-pipe-server.c
@@ -77,8 +77,6 @@ assuan_init_pipe_server (assuan_context_t ctx, int filedes[2])
assuan_fd_t infd = ASSUAN_INVALID_FD;
assuan_fd_t outfd = ASSUAN_INVALID_FD;
int is_usd = 0;
- static struct assuan_io io = { _assuan_simple_read, _assuan_simple_write,
- 0, 0 };
rc = _assuan_register_std_commands (ctx);
if (rc)
@@ -117,6 +115,10 @@ assuan_init_pipe_server (assuan_context_t ctx, int filedes[2])
ctx->is_server = 1;
ctx->engine.release = deinit_pipe_server;
+ ctx->engine.readfnc = _assuan_simple_read;
+ ctx->engine.writefnc = _assuan_simple_write;
+ ctx->engine.sendfd = NULL;
+ ctx->engine.receivefd = NULL;
ctx->pipe_mode = 1;
s = getenv ("_assuan_pipe_connect_pid");
@@ -135,8 +137,6 @@ assuan_init_pipe_server (assuan_context_t ctx, int filedes[2])
_assuan_init_uds_io (ctx);
ctx->deinit_handler = _assuan_uds_deinit;
}
- else
- ctx->io = &io;
return 0;
}
diff --git a/src/assuan-socket-connect.c b/src/assuan-socket-connect.c
index ac2df5b..21997f0 100644
--- a/src/assuan-socket-connect.c
+++ b/src/assuan-socket-connect.c
@@ -58,12 +58,12 @@ do_finish (assuan_context_t ctx)
{
if (ctx->inbound.fd != ASSUAN_INVALID_FD)
{
- _assuan_close (ctx->inbound.fd);
+ _assuan_close (ctx, ctx->inbound.fd);
ctx->inbound.fd = ASSUAN_INVALID_FD;
}
if (ctx->outbound.fd != ASSUAN_INVALID_FD)
{
- _assuan_close (ctx->outbound.fd);
+ _assuan_close (ctx, ctx->outbound.fd);
ctx->outbound.fd = ASSUAN_INVALID_FD;
}
}
@@ -96,8 +96,6 @@ assuan_socket_connect_ext (assuan_context_t ctx,
const char *name, pid_t server_pid,
unsigned int flags)
{
- static struct assuan_io io = { _assuan_simple_read, _assuan_simple_write,
- NULL, NULL };
gpg_error_t err;
assuan_fd_t fd;
struct sockaddr_un srvr_addr;
@@ -120,7 +118,7 @@ assuan_socket_connect_ext (assuan_context_t ctx,
if (strlen (name)+1 >= sizeof srvr_addr.sun_path)
return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
- fd = _assuan_sock_new (PF_LOCAL, SOCK_STREAM, 0);
+ fd = _assuan_sock_new (ctx, PF_LOCAL, SOCK_STREAM, 0);
if (fd == ASSUAN_INVALID_FD)
{
TRACE1 (ctx, ASSUAN_LOG_SYSIO, "assuan_socket_connect_ext", ctx,
@@ -135,17 +133,20 @@ assuan_socket_connect_ext (assuan_context_t ctx,
srvr_addr.sun_path[sizeof (srvr_addr.sun_path) - 1] = 0;
len = SUN_LEN (&srvr_addr);
- if ( _assuan_sock_connect (fd, (struct sockaddr *) &srvr_addr, len) == -1 )
+ if (_assuan_sock_connect (ctx, fd, (struct sockaddr *) &srvr_addr, len) == -1)
{
TRACE2 (ctx, ASSUAN_LOG_SYSIO, "assuan_socket_connect_ext", ctx,
"can't connect to `%s': %s\n", name, strerror (errno));
/* FIXME: Cleanup */
- _assuan_close (fd);
+ _assuan_close (ctx, fd);
return _assuan_error (ctx, GPG_ERR_ASS_CONNECT_FAILED);
}
- ctx->io = &io;
ctx->engine.release = _assuan_disconnect;
+ ctx->engine.readfnc = _assuan_simple_read;
+ ctx->engine.writefnc = _assuan_simple_write;
+ ctx->engine.sendfd = NULL;
+ ctx->engine.receivefd = NULL;
ctx->deinit_handler = ((flags&1))? _assuan_uds_deinit : do_deinit;
ctx->finish_handler = do_finish;
ctx->inbound.fd = fd;
diff --git a/src/assuan-socket-server.c b/src/assuan-socket-server.c
index b46a4e7..3487b19 100644
--- a/src/assuan-socket-server.c
+++ b/src/assuan-socket-server.c
@@ -96,9 +96,9 @@ accept_connection (assuan_context_t ctx)
{
return _assuan_error (ctx, gpg_err_code_from_syserror ());
}
- if (_assuan_sock_check_nonce (fd, &ctx->listen_nonce))
+ if (_assuan_sock_check_nonce (ctx, fd, &ctx->listen_nonce))
{
- _assuan_close (fd);
+ _assuan_close (ctx, fd);
return _assuan_error (ctx, GPG_ERR_ASS_ACCEPT_FAILED);
}
@@ -112,12 +112,12 @@ finish_connection (assuan_context_t ctx)
{
if (ctx->inbound.fd != ASSUAN_INVALID_FD)
{
- _assuan_close (ctx->inbound.fd);
+ _assuan_close (ctx, ctx->inbound.fd);
ctx->inbound.fd = ASSUAN_INVALID_FD;
}
if (ctx->outbound.fd != ASSUAN_INVALID_FD)
{
- _assuan_close (ctx->outbound.fd);
+ _assuan_close (ctx, ctx->outbound.fd);
ctx->outbound.fd = ASSUAN_INVALID_FD;
}
}
@@ -155,15 +155,16 @@ assuan_init_socket_server_ext (assuan_context_t ctx, assuan_fd_t fd,
unsigned int flags)
{
gpg_error_t rc;
- static struct assuan_io io = { _assuan_simple_read, _assuan_simple_write,
- 0, 0 };
rc = _assuan_register_std_commands (ctx);
if (rc)
return rc;
- ctx->io = &io;
ctx->engine.release = deinit_socket_server;
+ ctx->engine.readfnc = _assuan_simple_read;
+ ctx->engine.writefnc = _assuan_simple_write;
+ ctx->engine.sendfd = NULL;
+ ctx->engine.receivefd = NULL;
ctx->is_server = 1;
if (flags & 2)
ctx->pipe_mode = 1; /* We want a second accept to indicate EOF. */
diff --git a/src/assuan-socket.c b/src/assuan-socket.c
index e638503..a6ee7a4 100644
--- a/src/assuan-socket.c
+++ b/src/assuan-socket.c
@@ -144,33 +144,11 @@ read_port_and_nonce (const char *fname, unsigned short *port, char *nonce)
#endif /*HAVE_W32_SYSTEM*/
-
-int
-_assuan_close (assuan_fd_t fd)
-{
-#ifdef HAVE_W32_SYSTEM
- int rc = closesocket (HANDLE2SOCKET(fd));
- if (rc)
- errno = _assuan_sock_wsa2errno (WSAGetLastError ());
- if (rc && WSAGetLastError () == WSAENOTSOCK)
- {
- rc = CloseHandle (fd);
- if (rc)
- /* FIXME. */
- errno = EIO;
- }
- return rc;
-#else
- return close (fd);
-#endif
-}
-
-
/* Return a new socket. Note that under W32 we consider a socket the
same as an System Handle; all functions using such a handle know
about this dual use and act accordingly. */
assuan_fd_t
-_assuan_sock_new (int domain, int type, int proto)
+_assuan_sock_new (assuan_context_t ctx, int domain, int type, int proto)
{
#ifdef HAVE_W32_SYSTEM
assuan_fd_t res;
@@ -187,7 +165,8 @@ _assuan_sock_new (int domain, int type, int proto)
int
-_assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
+_assuan_sock_connect (assuan_context_t ctx, assuan_fd_t sockfd,
+ struct sockaddr *addr, int addrlen)
{
#ifdef HAVE_W32_SYSTEM
if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
@@ -199,7 +178,7 @@ _assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
int ret;
unaddr = (struct sockaddr_un *)addr;
- if (read_port_and_nonce (unaddr->sun_path, &port, nonce))
+ if (read_port_and_nonce (ctx, unaddr->sun_path, &port, nonce))
return -1;
myaddr.sin_family = AF_INET;
@@ -216,7 +195,7 @@ _assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
if (!ret)
{
/* Send the nonce. */
- ret = _assuan_io_write (sockfd, nonce, 16);
+ ret = _assuan_write (ctx, sockfd, nonce, 16);
if (ret >= 0 && ret != 16)
{
errno = EIO;
@@ -240,7 +219,8 @@ _assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
int
-_assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
+_assuan_sock_bind (assuan_context_t ctx, assuan_fd_t sockfd,
+ struct sockaddr *addr, int addrlen)
{
#ifdef HAVE_W32_SYSTEM
if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
@@ -312,8 +292,8 @@ _assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
int
-_assuan_sock_get_nonce (struct sockaddr *addr, int addrlen,
- assuan_sock_nonce_t *nonce)
+_assuan_sock_get_nonce (assuan_context_t ctx, struct sockaddr *addr,
+ int addrlen, assuan_sock_nonce_t *nonce)
{
#ifdef HAVE_W32_SYSTEM
if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
@@ -328,7 +308,7 @@ _assuan_sock_get_nonce (struct sockaddr *addr, int addrlen,
}
nonce->length = 16;
unaddr = (struct sockaddr_un *)addr;
- if (read_port_and_nonce (unaddr->sun_path, &port, nonce->nonce))
+ if (read_port_and_nonce (ctx, unaddr->sun_path, &port, nonce->nonce))
return -1;
}
else
@@ -346,7 +326,8 @@ _assuan_sock_get_nonce (struct sockaddr *addr, int addrlen,
int
-_assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce)
+_assuan_sock_check_nonce (assuan_context_t ctx, assuan_fd_t fd,
+ assuan_sock_nonce_t *nonce)
{
#ifdef HAVE_W32_SYSTEM
char buffer[16], *p;
@@ -367,12 +348,12 @@ _assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce)
errno = EINVAL;
return -1;
}
-
+
p = buffer;
nleft = 16;
while (nleft)
{
- n = _assuan_io_read (SOCKET2HANDLE(fd), p, nleft);
+ n = _assuan_read (ctx, SOCKET2HANDLE(fd), p, nleft);
if (n < 0 && errno == EINTR)
;
else if (n < 0 && errno == EAGAIN)
@@ -404,39 +385,83 @@ _assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce)
/* Public API. */
+
+/* In the future, we can allow access to sock_ctx, if that context's
+ hook functions need to be overridden. There can only be one global
+ assuan_sock_* user (one library or one application) with this
+ convenience interface, if non-standard hook functions are
+ needed. */
+static assuan_context_t sock_ctx;
+
+gpg_error_t
+assuan_sock_init ()
+{
+ gpg_error_t err;
+#ifdef HAVE_W32_SYSTEM
+ WSADATA wsadat;
+#endif
+
+ if (sock_ctx != NULL)
+ return 0;
+
+ err = assuan_new (&sock_ctx);
+
+#ifdef HAVE_W32_SYSTEM
+ if (! err)
+ WSAStartup (0x202, &wsadat);
+#endif
+
+ return err;
+}
+
+
+void
+assuan_sock_deinit ()
+{
+ if (sock_ctx == NULL)
+ return;
+
+#ifdef HAVE_W32_SYSTEM
+ WSACleanup ();
+#endif
+
+ assuan_release (sock_ctx);
+}
+
+
int
assuan_sock_close (assuan_fd_t fd)
{
- return _assuan_close (fd);
+ return _assuan_close (sock_ctx, fd);
}
assuan_fd_t
assuan_sock_new (int domain, int type, int proto)
{
- return _assuan_sock_new (domain, type, proto);
+ return _assuan_sock_new (sock_ctx, domain, type, proto);
}
int
assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
{
- return _assuan_sock_connect (sockfd, addr, addrlen);
+ return _assuan_sock_connect (sock_ctx, sockfd, addr, addrlen);
}
int
assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
{
- return _assuan_sock_bind (sockfd, addr, addrlen);
+ return _assuan_sock_bind (sock_ctx, sockfd, addr, addrlen);
}
int
assuan_sock_get_nonce (struct sockaddr *addr, int addrlen,
assuan_sock_nonce_t *nonce)
{
- return _assuan_sock_get_nonce (addr, addrlen, nonce);
+ return _assuan_sock_get_nonce (sock_ctx, addr, addrlen, nonce);
}
int
assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce)
{
- return _assuan_sock_check_nonce (fd, nonce);
+ return _assuan_sock_check_nonce (sock_ctx, fd, nonce);
}
diff --git a/src/assuan-uds.c b/src/assuan-uds.c
index 1c2d106..2bec03d 100644
--- a/src/assuan-uds.c
+++ b/src/assuan-uds.c
@@ -107,7 +107,7 @@ uds_reader (assuan_context_t ctx, void *buf, size_t buflen)
msg.msg_controllen = sizeof (control_u.control);
#endif
- len = _assuan_simple_recvmsg (ctx, &msg);
+ len = _assuan_recvmsg (ctx, ctx->inbound.fd, &msg, 0);
if (len < 0)
return -1;
if (len == 0)
@@ -133,7 +133,7 @@ uds_reader (assuan_context_t ctx, void *buf, size_t buflen)
TRACE1 (ctx, ASSUAN_LOG_SYSIO, "uds_reader", ctx,
"too many descriptors pending - "
"closing received descriptor %d", fd);
- _assuan_close (fd);
+ _assuan_close (ctx, fd);
}
else
ctx->uds.pendingfds[ctx->uds.pendingfdscount++] = fd;
@@ -181,7 +181,7 @@ uds_writer (assuan_context_t ctx, const void *buf, size_t buflen)
iovec.iov_base = (void*)buf;
iovec.iov_len = buflen;
- len = _assuan_simple_sendmsg (ctx, &msg);
+ len = _assuan_sendmsg (ctx, ctx->outbound.fd, &msg, 0);
return len;
#else /*HAVE_W32_SYSTEM*/
@@ -231,7 +231,7 @@ uds_sendfd (assuan_context_t ctx, assuan_fd_t fd)
cmptr->cmsg_type = SCM_RIGHTS;
*((int*)CMSG_DATA (cmptr)) = fd;
- len = _assuan_simple_sendmsg (ctx, &msg);
+ len = _assuan_sendmsg (ctx, ctx->outbound.fd, &msg, 0);
if (len < 0)
{
int saved_errno = errno;
@@ -281,7 +281,7 @@ _assuan_uds_close_fds (assuan_context_t ctx)
int i;
for (i = 0; i < ctx->uds.pendingfdscount; i++)
- _assuan_close (ctx->uds.pendingfds[i]);
+ _assuan_close (ctx, ctx->uds.pendingfds[i]);
ctx->uds.pendingfdscount = 0;
}
@@ -307,10 +307,11 @@ _assuan_uds_deinit (assuan_context_t ctx)
void
_assuan_init_uds_io (assuan_context_t ctx)
{
- static struct assuan_io io = { uds_reader, uds_writer,
- uds_sendfd, uds_receivefd };
+ ctx->engine.readfnc = uds_reader;
+ ctx->engine.writefnc = uds_writer;
+ ctx->engine.sendfd = uds_sendfd;
+ ctx->engine.receivefd = uds_receivefd;
- ctx->io = &io;
ctx->uds.buffer = 0;
ctx->uds.bufferoffset = 0;
ctx->uds.buffersize = 0;
diff --git a/src/assuan.c b/src/assuan.c
index 4848ec4..31263d4 100644
--- a/src/assuan.c
+++ b/src/assuan.c
@@ -92,6 +92,13 @@ assuan_get_log_cb (assuan_log_cb_t *log_cb, void **log_cb_data)
}
+void
+assuan_set_system_hooks (assuan_system_hooks_t system_hooks)
+{
+ _assuan_system_hooks_copy (&_assuan_system_hooks, system_hooks);
+}
+
+
/* Create a new Assuan context. The initial parameters are all needed
in the creation of the context. */
gpg_error_t
@@ -123,6 +130,7 @@ assuan_new_ext (assuan_context_t *r_ctx, gpg_err_source_t err_source,
return TRACE_ERR (gpg_err_code_from_syserror ());
memcpy (ctx, &wctx, sizeof (*ctx));
+ ctx->system = _assuan_system_hooks;
/* FIXME: Delegate to subsystems/engines, as the FDs are not our
responsibility (we don't deallocate them, for example). */
@@ -168,13 +176,13 @@ _assuan_reset (assuan_context_t ctx)
void
assuan_release (assuan_context_t ctx)
{
- if (ctx)
- {
- TRACE (ctx, ASSUAN_LOG_CTX, "assuan_release", ctx);
-
- _assuan_reset (ctx);
- /* None of the members that are our responsibility requires
- deallocation. */
- _assuan_free (ctx, ctx);
- }
+ TRACE (ctx, ASSUAN_LOG_CTX, "assuan_release", ctx);
+
+ if (! ctx)
+ return;
+
+ _assuan_reset (ctx);
+ /* None of the members that are our responsibility requires
+ deallocation. */
+ _assuan_free (ctx, ctx);
}
diff --git a/src/assuan.h b/src/assuan.h
index c0b1fea..c63e396 100644
--- a/src/assuan.h
+++ b/src/assuan.h
@@ -33,30 +33,19 @@
#endif
#endif /*!_ASSUAN_NO_SOCKET_WRAPPER*/
+#ifdef _WIN32
+typedef void *assuan_msghdr_t;
+#else
+typedef struct msghdr *assuan_msghdr_t;
+#endif
+
#include <gpg-error.h>
/* Compile time configuration:
#define _ASSUAN_NO_SOCKET_WRAPPER
- Do not include the definitions for the socket wrapper feature.
-
- The follwing macros are used internally in the implementation of
- libassuan:
-
- #define _ASSUAN_NO_PTH
-
- This avoids inclusion of special GNU Pth hacks.
-
- #define _ASSUAN_NO_FIXED_SIGNALS
-
- This disables changing of certain signal handler; i.e. SIGPIPE.
-
- #define _ASSUAN_USE_DOUBLE_FORK
-
- Use a double fork approach when connecting to a server through
- a pipe.
- */
+ Do not include the definitions for the socket wrapper feature. */
#ifdef __cplusplus
@@ -95,9 +84,11 @@ typedef struct assuan_context_s *assuan_context_t;
#ifdef _WIN32
typedef void *assuan_fd_t;
#define ASSUAN_INVALID_FD ((void*)(-1))
+#define ASSUAN_INVALID_PID ((pid_t) -1)
#else
typedef int assuan_fd_t;
#define ASSUAN_INVALID_FD (-1)
+#define ASSUAN_INVALID_PID ((pid_t) -1)
#endif
@@ -208,6 +199,8 @@ typedef unsigned int assuan_flag_t;
/* This flag indicates whether Assuan logging is in confidential mode.
You can use assuan_{begin,end}_condidential to change the mode. */
#define ASSUAN_CONFIDENTIAL 2
+/* This flag suppresses fix up of signal handlers for pipes. */
+#define ASSUAN_NO_FIXSIGNALS 3
/* For context CTX, set the flag FLAG to VALUE. Values for flags
are usually 1 or 0 but certain flags might allow for other values;
@@ -243,6 +236,52 @@ typedef unsigned int (*assuan_io_monitor_t) (assuan_context_t ctx, void *hook,
void assuan_set_io_monitor (assuan_context_t ctx,
assuan_io_monitor_t io_monitor, void *hook_data);
+
+#define ASSUAN_SYSTEM_HOOKS_VERSION 1
+struct assuan_system_hooks
+{
+ /* Always set to ASSUAN_SYTEM_HOOKS_VERSION. */
+ int version;
+
+ /* Sleep for the given number of microseconds. */
+ void (*usleep) (assuan_context_t ctx, unsigned int usec);
+
+ /* Create a pipe with an inheritable end. */
+ int (*pipe) (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx);
+
+ /* Close the given file descriptor, created with _assuan_pipe or one
+ of the socket functions. */
+ int (*close) (assuan_context_t ctx, assuan_fd_t fd);
+
+
+ ssize_t (*read) (assuan_context_t ctx, assuan_fd_t fd, void *buffer,
+ size_t size);
+ ssize_t (*write) (assuan_context_t ctx, assuan_fd_t fd,
+ const void *buffer, size_t size);
+
+ int (*recvmsg) (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
+ int flags);
+ int (*sendmsg) (assuan_context_t ctx, assuan_fd_t fd,
+ const assuan_msghdr_t msg, int flags);
+
+ /* 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). */
+ int (*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);
+
+ /* If action is 0, like waitpid. If action is 1, just release the PID? */
+ pid_t (*waitpid) (assuan_context_t ctx, pid_t pid,
+ int action, int *status, int options);
+ int (*socketpair) (assuan_context_t ctx, int namespace, int style,
+ int protocol, assuan_fd_t filedes[2]);
+};
+typedef struct assuan_system_hooks *assuan_system_hooks_t;
+
/* Configuration of the default log handler. */
@@ -328,11 +367,11 @@ void assuan_set_sock_nonce (assuan_context_t ctx, assuan_sock_nonce_t *nonce);
gpg_error_t assuan_pipe_connect (assuan_context_t ctx,
const char *name,
const char *argv[],
- int *fd_child_list);
+ assuan_fd_t *fd_child_list);
gpg_error_t assuan_pipe_connect_ext (assuan_context_t ctx,
const char *name,
const char *argv[],
- int *fd_child_list,
+ assuan_fd_t *fd_child_list,
void (*atfork) (void *, int),
void *atforkvalue,
unsigned int flags);
@@ -401,6 +440,8 @@ gpg_error_t assuan_set_error (assuan_context_t ctx, gpg_error_t err, const char
/* These are socket wrapper functions to support an emulation of Unix
domain sockets on Windows W32. */
+gpg_error_t assuan_sock_init (void);
+void assuan_sock_deinit (void);
int assuan_sock_close (assuan_fd_t fd);
assuan_fd_t assuan_sock_new (int domain, int type, int proto);
int assuan_sock_connect (assuan_fd_t sockfd,
@@ -410,6 +451,132 @@ int assuan_sock_get_nonce (struct sockaddr *addr, int addrlen,
assuan_sock_nonce_t *nonce);
int assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce);
+
+/* Set the default or per context system callbacks. This is
+ irreversible. */
+void assuan_set_system_hooks (assuan_system_hooks_t system_hooks);
+
+void assuan_ctx_set_system_hooks (assuan_context_t ctx,
+ assuan_system_hooks_t system_hooks);
+
+int __assuan_pipe (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx);
+int __assuan_close (assuan_context_t ctx, assuan_fd_t fd);
+int __assuan_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 __assuan_socketpair (assuan_context_t ctx, int namespace, int style,
+ int protocol, assuan_fd_t filedes[2]);
+
+#ifdef _WIN32
+#define _ASSUAN_SYSTEM_PTH_IMPL \
+ static int _assuan_pth_recvmsg (assuan_context_t ctx, assuan_fd_t fd, \
+ assuan_msghdr_t msg, int flags) \
+ { \
+ (void) ctx; \
+ errno = ENOSYS; \
+ return -1; \
+ } \
+ static int _assuan_pth_sendmsg (assuan_context_t ctx, assuan_fd_t fd, \
+ const assuan_msghdr_t msg, int flags) \
+ { \
+ (void) ctx; \
+ errno = ENOSYS; \
+ return -1; \
+ }
+#else
+#define _ASSUAN_SYSTEM_PTH_IMPL \
+ static int _assuan_pth_recvmsg (assuan_context_t ctx, assuan_fd_t fd, \
+ assuan_msghdr_t msg, int flags) \
+ { \
+ /* Pth does not provide a recvmsg function. We implement it. */ \
+ int ret; \
+ int fdmode; \
+ \
+ (void) ctx; \
+ fdmode = pth_fdmode (fd, PTH_FDMODE_POLL); \
+ if (fdmode == PTH_FDMODE_ERROR) \
+ { \
+ errno = EBADF; \
+ return -1; \
+ } \
+ if (fdmode == PTH_FDMODE_BLOCK) \
+ { \
+ fd_set fds; \
+ \
+ FD_ZERO (&fds); \
+ FD_SET (fd, &fds); \
+ while ((ret = pth_select (fd + 1, &fds, NULL, NULL, NULL)) < 0 \
+ && errno == EINTR) \
+ ; \
+ if (ret < 0) \
+ return -1; \
+ } \
+ \
+ while ((ret = recvmsg (fd, msg, flags)) == -1 && errno == EINTR) \
+ ; \
+ return ret; \
+ } \
+ static int _assuan_pth_sendmsg (assuan_context_t ctx, assuan_fd_t fd, \
+ const assuan_msghdr_t msg, int flags) \
+ { \
+ /* Pth does not provide a sendmsg function. We implement it. */ \
+ int ret; \
+ int fdmode; \
+ \
+ (void) ctx; \
+ fdmode = pth_fdmode (fd, PTH_FDMODE_POLL); \
+ if (fdmode == PTH_FDMODE_ERROR) \
+ { \
+ errno = EBADF; \
+ return -1; \
+ } \
+ if (fdmode == PTH_FDMODE_BLOCK) \
+ { \
+ fd_set fds; \
+ \
+ FD_ZERO (&fds); \
+ FD_SET (fd, &fds); \
+ while ((ret = pth_select (fd + 1, NULL, &fds, NULL, NULL)) < 0 \
+ && errno == EINTR) \
+ ; \
+ if (ret < 0) \
+ return -1; \
+ } \
+ \
+ while ((ret = sendmsg (fd, msg, flags)) == -1 && errno == EINTR) \
+ ; \
+ return ret; \
+ }
+#endif
+
+
+#define ASSUAN_SYSTEM_PTH_IMPL \
+ static void _assuan_pth_usleep (assuan_context_t ctx, unsigned int usec) \
+ { (void) ctx; pth_usleep (usec); } \
+ static ssize_t _assuan_pth_read (assuan_context_t ctx, assuan_fd_t fd, \
+ void *buffer, size_t size) \
+ { (void) ctx; return pth_read (fd, buffer, size); } \
+ static ssize_t _assuan_pth_write (assuan_context_t ctx, assuan_fd_t fd, \
+ const void *buffer, size_t size) \
+ { (void) ctx; return pth_write (fd, buffer, size); } \
+ _ASSUAN_SYSTEM_PTH_IMPL \
+ static pid_t _assuan_pth_waitpid (assuan_context_t ctx, pid_t pid, \
+ int nowait, int *status, int options) \
+ { (void) ctx; \
+ if (!nowait) return pth_waitpid (pid, status, options); \
+ else return 0; } \
+ \
+ struct assuan_system_hooks _assuan_system_pth = \
+ { ASSUAN_SYSTEM_HOOKS_VERSION, _assuan_pth_usleep, __assuan_pipe, \
+ __assuan_close, _assuan_pth_read, _assuan_pth_write, \
+ _assuan_pth_recvmsg, _assuan_pth_sendmsg, \
+ __assuan_spawn, _assuan_pth_waitpid, __assuan_socketpair }
+
+extern struct assuan_system_hooks _assuan_system_pth;
+#define ASSUAN_SYSTEM_PTH &_assuan_system_pth
+
#ifdef __cplusplus
}
diff --git a/src/context.c b/src/context.c
index d87672b..3e707ca 100644
--- a/src/context.c
+++ b/src/context.c
@@ -28,10 +28,13 @@
/* Set user-data in a context. */
void
-assuan_set_pointer (assuan_context_t ctx, void *pointer)
+assuan_set_pointer (assuan_context_t ctx, void *user_pointer)
{
+ TRACE1 (ctx, ASSUAN_LOG_CTX, "assuan_set_pointer", ctx,
+ "user_pointer=%p", user_pointer);
+
if (ctx)
- ctx->user_pointer = pointer;
+ ctx->user_pointer = user_pointer;
}
@@ -39,6 +42,9 @@ assuan_set_pointer (assuan_context_t ctx, void *pointer)
void *
assuan_get_pointer (assuan_context_t ctx)
{
+ TRACE1 (ctx, ASSUAN_LOG_CTX, "assuan_get_pointer", ctx,
+ "ctx->user_pointer=%p", ctx ? ctx->user_pointer : NULL);
+
if (! ctx)
return NULL;
@@ -52,6 +58,9 @@ assuan_get_pointer (assuan_context_t ctx)
void
assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value)
{
+ TRACE2 (ctx, ASSUAN_LOG_CTX, "assuan_set_flag", ctx,
+ "flag=%i,value=%i", flag, value);
+
if (!ctx)
return;
@@ -64,6 +73,10 @@ assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value)
case ASSUAN_CONFIDENTIAL:
ctx->flags.confidential = value;
break;
+
+ case ASSUAN_NO_FIXSIGNALS:
+ ctx->flags.no_fixsignals = value;
+ break;
}
}
@@ -72,18 +85,29 @@ assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value)
int
assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag)
{
+ int res = 0;
+ TRACE_BEG1 (ctx, ASSUAN_LOG_CTX, "assuan_get_flag", ctx,
+ "flag=%i", flag);
+
if (! ctx)
return 0;
switch (flag)
{
case ASSUAN_NO_WAITPID:
- return ctx->flags.no_waitpid;
+ res = ctx->flags.no_waitpid;
+ break;
+
case ASSUAN_CONFIDENTIAL:
- return ctx->flags.confidential;
+ res = ctx->flags.confidential;
+ break;
+
+ case ASSUAN_NO_FIXSIGNALS:
+ res = ctx->flags.no_fixsignals;
+ break;
}
- return 0;
+ return TRACE_SUC1 ("flag_value=%i", res);
}
@@ -103,15 +127,31 @@ assuan_end_confidential (assuan_context_t ctx)
}
+/* Set the system callbacks. */
+void
+assuan_ctx_set_system_hooks (assuan_context_t ctx,
+ assuan_system_hooks_t system_hooks)
+{
+ TRACE2 (ctx, ASSUAN_LOG_CTX, "assuan_set_system_hooks", ctx,
+ "system_hooks=%p (version %i)", system_hooks,
+ system_hooks->version);
+
+ _assuan_system_hooks_copy (&ctx->system, system_hooks);
+}
+
+
/* Set the IO monitor function. */
void assuan_set_io_monitor (assuan_context_t ctx,
assuan_io_monitor_t io_monitor, void *hook_data)
{
- if (ctx)
- {
- ctx->io_monitor = io_monitor;
- ctx->io_monitor_data = hook_data;
- }
+ TRACE2 (ctx, ASSUAN_LOG_CTX, "assuan_set_io_monitor", ctx,
+ "io_monitor=%p,hook_data=%p", io_monitor, hook_data);
+
+ if (! ctx)
+ return;
+
+ ctx->io_monitor = io_monitor;
+ ctx->io_monitor_data = hook_data;
}
@@ -121,6 +161,10 @@ void assuan_set_io_monitor (assuan_context_t ctx,
gpg_error_t
assuan_set_error (assuan_context_t ctx, gpg_error_t err, const char *text)
{
+ TRACE4 (ctx, ASSUAN_LOG_CTX, "assuan_set_error", ctx,
+ "err=%i (%s,%s),text=%s", err, gpg_strsource (err),
+ gpg_strerror (err), text);
+
ctx->err_no = err;
ctx->err_str = text;
return err;
diff --git a/src/conversion.c b/src/conversion.c
index af5026e..88a7fd0 100644
--- a/src/conversion.c
+++ b/src/conversion.c
@@ -1,6 +1,6 @@
/* conversion.c - String conversion helper functions.
Copyright (C) 2000 Werner Koch (dd9jn)
- Copyright (C) 2001, 2002, 2003, 2004, 2007 g10 Code GmbH
+ Copyright (C) 2001, 2002, 2003, 2004, 2007, 2009 g10 Code GmbH
This file is part of Assuan.
@@ -25,9 +25,6 @@
#include <stdlib.h>
#include <string.h>
-/* Solaris 8 needs sys/types.h before time.h. */
-#include <sys/types.h>
-#include <time.h>
#include <errno.h>
#include <ctype.h>
diff --git a/src/debug.h b/src/debug.h
index 13e5419..4b4a41d 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -123,6 +123,12 @@ void _assuan_debug_buffer (assuan_context_t ctx, unsigned int cat,
"%s (%s=%p): enter: " fmt "\n", \
_assuan_trace_func, _assuan_trace_tagname, \
_assuan_trace_tag, arg1, arg2, arg3, arg4), 0
+#define TRACE_BEG6(ctx, lvl, name, tag, fmt, arg1, arg2, arg3, arg4,arg5,arg6) \
+ _TRACE (ctx, lvl, name, tag); \
+ _assuan_debug (_assuan_trace_context, _assuan_trace_level, \
+ "%s (%s=%p): enter: " fmt "\n", \
+ _assuan_trace_func, _assuan_trace_tagname, \
+ _assuan_trace_tag, arg1, arg2, arg3, arg4, arg5, arg6), 0
#define TRACE_BEG8(ctx, lvl, name, tag, fmt, arg1, arg2, arg3, arg4, \
arg5, arg6, arg7, arg8) \
@@ -149,6 +155,10 @@ void _assuan_debug_buffer (assuan_context_t ctx, unsigned int cat,
_assuan_debug (ctx, lvl, "%s (%s=%p): call: " fmt "\n", \
name, STRINGIFY (tag), (void *) (uintptr_t) tag, arg1, \
arg2, arg3), 0
+#define TRACE4(ctx, lvl, name, tag, fmt, arg1, arg2, arg3, arg4) \
+ _assuan_debug (ctx, lvl, "%s (%s=%p): call: " fmt "\n", \
+ name, STRINGIFY (tag), (void *) (uintptr_t) tag, arg1, \
+ arg2, arg3, arg4), 0
#define TRACE6(ctx, lvl, name, tag, fmt, arg1, arg2, arg3, arg4, arg5, arg6) \
_assuan_debug (ctx, lvl, "%s (%s=%p): call: " fmt "\n", \
name, STRINGIFY (tag), (void *) (uintptr_t) tag, arg1, \
@@ -171,7 +181,7 @@ void _assuan_debug_buffer (assuan_context_t ctx, unsigned int cat,
_assuan_trace_tag, strerror (errno)), (res))
#define TRACE_SYSERR(res) \
res == 0 ? ((void) (TRACE_SUC1 ("result=%i", res)), (res)) : \
- (_assuan_debug (_assuan_trace_level, "%s (%s=%p): error: %s\n", \
+ (_assuan_debug (_assuan_trace_context, _assuan_trace_level, "%s (%s=%p): error: %s\n", \
_assuan_trace_func, _assuan_trace_tagname, \
_assuan_trace_tag, strerror (res)), (res))
diff --git a/src/libassuan-config.in b/src/libassuan-config.in
index 50c9805..561ff96 100644
--- a/src/libassuan-config.in
+++ b/src/libassuan-config.in
@@ -18,8 +18,6 @@ lib="@LIBASSUAN_CONFIG_LIB@"
extralibs="@LIBASSUAN_CONFIG_EXTRA_LIBS@ $gpg_error_libs"
cflags="@LIBASSUAN_CONFIG_CFLAGS@ $gpg_error_cflags"
api_version="@LIBASSUAN_CONFIG_API_VERSION@"
-all_thread_modules="@LIBASSUAN_CONFIG_THREAD_MODULES@"
-thread_module=
prefix=@prefix@
exec_prefix=@exec_prefix@
includes=""
@@ -31,18 +29,11 @@ echo_prefix=no
echo_exec_prefix=no
-if test x"$all_thread_modules" = x; then
- all_thread_modules="none pthread"
-else
- all_thread_modules="none pthread $all_thread_modules"
-fi
-
usage()
{
cat <<EOF
Usage: $PGM [OPTIONS]
Options:
- [--thread={`echo "${all_thread_modules}" | sed 's/ /|/g'`}]
[--prefix[=DIR]]
[--exec-prefix[=DIR]]
[--version]
@@ -82,22 +73,6 @@ while test $# -gt 0; do
--api-version)
echo_api_version=yes
;;
- --thread=*)
- for mod in $all_thread_modules; do
- if test "$mod" = "$optarg"; then
- thread_module="-$mod"
- fi
- done
- if test "x$thread_module" = "x"; then
- usage 1 1>&2
- fi
- if test "$thread_module" = "-none"; then
- thread_module=""
- fi
- if test "$thread_module" = "-pthread"; then
- thread_module=""
- fi
- ;;
--cflags)
echo_cflags=yes
;;
@@ -145,5 +120,5 @@ if test "$echo_libs" = "yes"; then
fi
done
fi
- echo $libdirs $lib${thread_module} $extralibs
+ echo $libdirs $lib $extralibs
fi
diff --git a/src/libassuan.def b/src/libassuan.def
index b2450d8..9750748 100644
--- a/src/libassuan.def
+++ b/src/libassuan.def
@@ -84,7 +84,16 @@ EXPORTS
assuan_transact @63
assuan_write_line @64
assuan_write_status @65
+ assuan_sock_init
+ assuan_sock_deinit
assuan_get_command_name @66
+ __assuan_pipe
+ __assuan_close
+ __assuan_spawn
+ __assuan_socketpair
+ assuan_set_system_hooks
+ assuan_ctx_set_system_hooks
+
; END
diff --git a/src/libassuan.m4 b/src/libassuan.m4
index 004eee3..bac1be8 100644
--- a/src/libassuan.m4
+++ b/src/libassuan.m4
@@ -131,45 +131,3 @@ AC_DEFUN([AM_PATH_LIBASSUAN],
AC_SUBST(LIBASSUAN_CFLAGS)
AC_SUBST(LIBASSUAN_LIBS)
])
-
-
-dnl AM_PATH_LIBASSUAN_PTH([MINIMUM-VERSION,
-dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
-dnl Test for libassuan and define LIBASSUAN_PTH_CFLAGS and LIBASSUAN_PTH_LIBS
-dnl
-AC_DEFUN([AM_PATH_LIBASSUAN_PTH],
-[ _AM_PATH_LIBASSUAN_COMMON($1,pth)
- if test $ok = yes; then
- LIBASSUAN_PTH_CFLAGS=`$LIBASSUAN_CONFIG $libassuan_config_args --thread=pth --cflags`
- LIBASSUAN_PTH_LIBS=`$LIBASSUAN_CONFIG $libassuan_config_args --thread=pth --libs`
- ifelse([$2], , :, [$2])
- else
- LIBASSUAN_PTH_CFLAGS=""
- LIBASSUAN_PTH_LIBS=""
- ifelse([$3], , :, [$3])
- fi
- AC_SUBST(LIBASSUAN_PTH_CFLAGS)
- AC_SUBST(LIBASSUAN_PTH_LIBS)
-])
-
-
-dnl AM_PATH_LIBASSUAN_PTHREAD([MINIMUM-VERSION,
-dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
-dnl Test for libassuan and define LIBASSUAN_PTHREAD_CFLAGS
-dnl and LIBASSUAN_PTHREAD_LIBS
-dnl
-AC_DEFUN([AM_PATH_LIBASSUAN_PTHREAD],
-[ _AM_PATH_LIBASSUAN_COMMON($1,pthread)
- if test $ok = yes; then
- LIBASSUAN_PTHREAD_CFLAGS=`$LIBASSUAN_CONFIG $libassuan_config_args --thread=pthread --cflags`
- LIBASSUAN_PTHREAD_LIBS=`$LIBASSUAN_CONFIG $libassuan_config_args --thread=pthread --libs`
- ifelse([$2], , :, [$2])
- else
- LIBASSUAN_PTHREAD_CFLAGS=""
- LIBASSUAN_PTHREAD_LIBS=""
- ifelse([$3], , :, [$3])
- fi
- AC_SUBST(LIBASSUAN_PTHREAD_CFLAGS)
- AC_SUBST(LIBASSUAN_PTHREAD_LIBS)
-])
-
diff --git a/src/libassuan.vers b/src/libassuan.vers
index e4f6a7a..9b5b5e0 100644
--- a/src/libassuan.vers
+++ b/src/libassuan.vers
@@ -91,6 +91,14 @@ LIBASSUAN_1.0 {
assuan_new_ext;
assuan_new;
assuan_release;
+ assuan_sock_init;
+ assuan_sock_deinit;
+ __assuan_pipe;
+ __assuan_close;
+ __assuan_spawn;
+ __assuan_socketpair;
+ assuan_set_system_hooks;
+ assuan_ctx_set_system_hooks;
local:
*;
diff --git a/src/system.c b/src/system.c
index dd0c079..91a5a10 100644
--- a/src/system.c
+++ b/src/system.c
@@ -24,10 +24,25 @@
#include <stdlib.h>
#include <errno.h>
+/* Solaris 8 needs sys/types.h before time.h. */
+#include <sys/types.h>
+#include <time.h>
+#include <fcntl.h>
+#ifdef HAVE_W32_SYSTEM
+# include <windows.h>
+#else
+# include <sys/wait.h>
+#endif
#include "assuan-defs.h"
#include "debug.h"
+#ifdef _POSIX_OPEN_MAX
+#define MAX_OPEN_FDS _POSIX_OPEN_MAX
+#else
+#define MAX_OPEN_FDS 20
+#endif
+
/* Manage memory specific to a context. */
@@ -70,3 +85,793 @@ _assuan_free (assuan_context_t ctx, void *ptr)
if (ptr)
ctx->malloc_hooks.free (ptr);
}
+
+
+/* Copy the system hooks struct, paying attention to version
+ differences. SRC is usually from the user, DST MUST be from the
+ library. */
+void
+_assuan_system_hooks_copy (assuan_system_hooks_t dst,
+ assuan_system_hooks_t src)
+
+{
+ memset (dst, '\0', sizeof (*dst));
+
+ dst->version = ASSUAN_SYSTEM_HOOKS_VERSION;
+ if (src->version >= 1)
+ {
+ dst->usleep = src->usleep;
+ dst->pipe = src->pipe;
+ dst->close = src->close;
+ dst->read = src->read;
+ dst->write = src->write;
+ dst->sendmsg = src->sendmsg;
+ dst->recvmsg = src->recvmsg;
+ dst->spawn = src->spawn;
+ dst->waitpid = src->waitpid;
+ dst->socketpair = src->socketpair;
+ }
+ if (src->version > 1)
+ /* FIXME. Application uses newer version of the library. What to
+ do? */
+ ;
+}
+
+
+/* Sleep for the given number of microseconds. Default
+ implementation. */
+static void
+__assuan_usleep (assuan_context_t ctx, unsigned int usec)
+{
+ if (! usec)
+ return;
+
+#ifdef HAVE_NANOSLEEP
+ {
+ struct timespec req;
+ struct timespec rem;
+
+ req.tv_sec = 0;
+ req.tv_nsec = usec * 1000;
+
+ while (nanosleep (&req, &rem) < 0 && errno == EINTR)
+ req = rem;
+ }
+#elif defined(HAVE_W32_SYSTEM)
+ Sleep (usec / 1000);
+#else
+ {
+ struct timeval tv;
+
+ tv.tv_sec = usec / 1000000;
+ tv.tv_usec = usec % 1000000;
+ select (0, NULL, NULL, NULL, &tv);
+ }
+#endif
+}
+
+
+/* Sleep for the given number of microseconds. */
+void
+_assuan_usleep (assuan_context_t ctx, unsigned int usec)
+{
+ TRACE1 (ctx, ASSUAN_LOG_SYSIO, "_assuan_usleep", ctx,
+ "usec=%u", usec);
+
+ return (ctx->system.usleep) (ctx, usec);
+}
+
+
+/* Create a pipe with one inheritable end. Default implementation. */
+int
+__assuan_pipe (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx)
+{
+#ifdef HAVE_W32_SYSTEM
+ HANDLE rh;
+ HANDLE wh;
+ HANDLE th;
+ SECURITY_ATTRIBUTES sec_attr;
+ TRACE_BEG2 (ctx, ASSUAN_LOG_SYSIO, "__assuan_pipe", ctx,
+ "inherit_idx=%i (Assuan uses it for %s)",
+ inherit_idx, inherit_idx ? "reading" : "writing");
+
+ memset (&sec_attr, 0, sizeof (sec_attr));
+ sec_attr.nLength = sizeof (sec_attr);
+ sec_attr.bInheritHandle = FALSE;
+
+ if (! CreatePipe (&rh, &wh, &sec_attr, 0))
+ {
+ TRACE_LOG1 ("CreatePipe failed: %s", _assuan_w32_strerror (ctx, -1));
+ errno = EIO;
+ return TRACE_SYSRES (-1);
+ }
+
+ if (! DuplicateHandle (GetCurrentProcess(), (inherit_idx == 0) ? rh : wh,
+ GetCurrentProcess(), &th, 0,
+ TRUE, DUPLICATE_SAME_ACCESS ))
+ {
+ TRACE_LOG1 ("DuplicateHandle failed: %s", _assuan_w32_strerror (ctx, -1));
+ CloseHandle (rh);
+ CloseHandle (wh);
+ errno = EIO;
+ return TRACE_SYSRES (-1);
+ }
+ if (inherit_idx == 0)
+ {
+ CloseHandle (rh);
+ rh = th;
+ }
+ else
+ {
+ CloseHandle (wh);
+ wh = th;
+ }
+
+ fd[0] = rh;
+ fd[1] = wh;
+
+ return TRACE_SUC ();
+#else
+ return pipe (fd);
+#endif
+}
+
+
+/* Create a pipe with one inheritable end. */
+int
+_assuan_pipe (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx)
+{
+ return (ctx->system.pipe) (ctx, fd, inherit_idx);
+}
+
+
+/* Close the given file descriptor, created with _assuan_pipe or one
+ of the socket functions. Default implementation. */
+int
+__assuan_close (assuan_context_t ctx, assuan_fd_t fd)
+{
+#ifdef HAVE_W32_SYSTEM
+ int rc = closesocket (HANDLE2SOCKET(fd));
+ if (rc)
+ errno = _assuan_sock_wsa2errno (WSAGetLastError ());
+ if (rc && WSAGetLastError () == WSAENOTSOCK)
+ {
+ rc = CloseHandle (fd);
+ if (rc)
+ /* FIXME. */
+ errno = EIO;
+ }
+ return rc;
+#else
+ return close (fd);
+#endif
+}
+
+
+/* Close the given file descriptor, created with _assuan_pipe or one
+ of the socket functions. */
+int
+_assuan_close (assuan_context_t ctx, assuan_fd_t fd)
+{
+ TRACE1 (ctx, ASSUAN_LOG_SYSIO, "_assuan_close", ctx,
+ "fd=0x%x", fd);
+
+ return (ctx->system.close) (ctx, fd);
+}
+
+
+static ssize_t
+__assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
+{
+#ifdef HAVE_W32_SYSTEM
+ /* Due to the peculiarities of the W32 API we can't use read for a
+ network socket and thus we try to use recv first and fallback to
+ read if recv detects that it is not a network socket. */
+ int res;
+
+ res = recv (HANDLE2SOCKET (fd), buffer, size, 0);
+ if (res == -1)
+ {
+ switch (WSAGetLastError ())
+ {
+ case WSAENOTSOCK:
+ {
+ DWORD nread = 0;
+
+ res = ReadFile (fd, buffer, size, &nread, NULL);
+ if (! res)
+ {
+ switch (GetLastError ())
+ {
+ case ERROR_BROKEN_PIPE:
+ errno = EPIPE;
+ break;
+
+ default:
+ errno = EIO;
+ }
+ res = -1;
+ }
+ else
+ res = (int) nread;
+ }
+ break;
+
+ case WSAEWOULDBLOCK:
+ errno = EAGAIN;
+ break;
+
+ case ERROR_BROKEN_PIPE:
+ errno = EPIPE;
+ break;
+
+ default:
+ errno = EIO;
+ break;
+ }
+ }
+ return res;
+#else /*!HAVE_W32_SYSTEM*/
+ return read (fd, buffer, size);
+#endif /*!HAVE_W32_SYSTEM*/
+}
+
+
+ssize_t
+_assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
+{
+ return (ctx->system.read) (ctx, fd, buffer, size);
+}
+
+
+static ssize_t
+__assuan_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer,
+ size_t size)
+{
+#ifdef HAVE_W32_SYSTEM
+ /* Due to the peculiarities of the W32 API we can't use write for a
+ network socket and thus we try to use send first and fallback to
+ write if send detects that it is not a network socket. */
+ int res;
+
+ res = send (HANDLE2SOCKET (fd), buffer, size, 0);
+ if (res == -1 && WSAGetLastError () == WSAENOTSOCK)
+ {
+ DWORD nwrite;
+
+ res = WriteFile (fd, buffer, size, &nwrite, NULL);
+ if (! res)
+ {
+ switch (GetLastError ())
+ {
+ case ERROR_BROKEN_PIPE:
+ case ERROR_NO_DATA:
+ errno = EPIPE;
+ break;
+
+ default:
+ errno = EIO;
+ break;
+ }
+ res = -1;
+ }
+ else
+ res = (int) nwrite;
+ }
+ return res;
+#else /*!HAVE_W32_SYSTEM*/
+ return write (fd, buffer, size);
+#endif /*!HAVE_W32_SYSTEM*/
+}
+
+
+ssize_t
+_assuan_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer,
+ size_t size)
+{
+ return (ctx->system.write) (ctx, fd, buffer, size);
+}
+
+
+static int
+__assuan_recvmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
+ int flags)
+{
+#ifdef HAVE_W32_SYSTEM
+ errno = ENOSYS;
+ return -1;
+#else
+ int ret;
+ do
+ ret = recvmsg (fd, msg, flags);
+ while (ret == -1 && errno == EINTR);
+
+ return ret;
+#endif
+}
+
+
+int
+_assuan_recvmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
+ int flags)
+{
+ return (ctx->system.recvmsg) (ctx, fd, msg, flags);
+}
+
+
+static int
+__assuan_sendmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
+ int flags)
+{
+#ifdef HAVE_W32_SYSTEM
+ errno = ENOSYS;
+ return -1;
+#else
+ int ret;
+ do
+ ret = sendmsg (fd, msg, flags);
+ while (ret == -1 && errno == EINTR);
+
+ return ret;
+#endif
+}
+
+
+int
+_assuan_sendmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
+ int flags)
+{
+ return (ctx->system.sendmsg) (ctx, fd, msg, flags);
+}
+
+
+#ifdef HAVE_W32_SYSTEM
+/* Build a command line for use with W32's CreateProcess. On success
+ CMDLINE gets the address of a newly allocated string. */
+static int
+build_w32_commandline (assuan_context_t ctx, const char * const *argv,
+ char **cmdline)
+{
+ int i, n;
+ const char *s;
+ char *buf, *p;
+
+ *cmdline = NULL;
+ n = 0;
+ for (i=0; (s = argv[i]); i++)
+ {
+ n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */
+ for (; *s; s++)
+ if (*s == '\"')
+ n++; /* Need to double inner quotes. */
+ }
+ n++;
+
+ buf = p = _assuan_malloc (ctx, n);
+ if (! buf)
+ return -1;
+
+ for (i = 0; argv[i]; i++)
+ {
+ if (i)
+ p = stpcpy (p, " ");
+ if (! *argv[i]) /* Empty string. */
+ p = stpcpy (p, "\"\"");
+ else if (strpbrk (argv[i], " \t\n\v\f\""))
+ {
+ p = stpcpy (p, "\"");
+ for (s = argv[i]; *s; s++)
+ {
+ *p++ = *s;
+ if (*s == '\"')
+ *p++ = *s;
+ }
+ *p++ = '\"';
+ *p = 0;
+ }
+ else
+ p = stpcpy (p, argv[i]);
+ }
+
+ *cmdline= buf;
+ return 0;
+}
+
+
+int
+__assuan_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)
+{
+ SECURITY_ATTRIBUTES sec_attr;
+ PROCESS_INFORMATION pi =
+ {
+ NULL, /* Returns process handle. */
+ 0, /* Returns primary thread handle. */
+ 0, /* Returns pid. */
+ 0 /* Returns tid. */
+ };
+ STARTUPINFO si;
+ int fd;
+ int *fdp;
+ char *cmdline;
+ HANDLE nullfd = INVALID_HANDLE_VALUE;
+
+ /* fixme: Actually we should set the "_assuan_pipe_connect_pid" env
+ variable. However this requires us to write a full environment
+ handler, because the strings are expected in sorted order. The
+ suggestion given in the MS Reference Library, to save the old
+ value, changeit, create proces and restore it, is not thread
+ safe. */
+
+ /* Build the command line. */
+ if (build_w32_commandline (ctx, argv, &cmdline))
+ return -1;
+
+ /* Start the process. */
+ memset (&sec_attr, 0, sizeof sec_attr);
+ sec_attr.nLength = sizeof sec_attr;
+ sec_attr.bInheritHandle = FALSE;
+
+ memset (&si, 0, sizeof si);
+ si.cb = sizeof (si);
+ si.dwFlags = STARTF_USESTDHANDLES;
+ /* FIXME: Dup to nul if ASSUAN_INVALID_FD. */
+ si.hStdInput = fd_in;
+ si.hStdOutput = fd_out;
+
+ /* Dup stderr to /dev/null unless it is in the list of FDs to be
+ passed to the child. */
+ fd = fileno (stderr);
+ fdp = fd_child_list;
+ if (fdp)
+ {
+ for (; *fdp != -1 && *fdp != fd; fdp++)
+ ;
+ }
+ if (!fdp || *fdp == -1)
+ {
+ nullfd = CreateFile ("nul", GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, 0, NULL);
+ if (nullfd == INVALID_HANDLE_VALUE)
+ {
+ TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
+ "can't open `nul': %s", w32_strerror (ctx, -1));
+ _assuan_free (cmdline);
+ return -1;
+ }
+ si.hStdError = nullfd;
+ }
+ else
+ si.hStdError = (void*)_get_osfhandle (fd);
+
+
+ /* Note: We inherit all handles flagged as inheritable. This seems
+ to be a security flaw but there seems to be no way of selecting
+ handles to inherit. */
+ /* _assuan_log_printf ("CreateProcess, path=`%s' cmdline=`%s'\n", */
+ /* name, cmdline); */
+ if (!CreateProcess (name, /* Program to start. */
+ cmdline, /* Command line arguments. */
+ &sec_attr, /* Process security attributes. */
+ &sec_attr, /* Thread security attributes. */
+ TRUE, /* Inherit handles. */
+ (CREATE_DEFAULT_ERROR_MODE
+ | ((flags & 128)? DETACHED_PROCESS : 0)
+ | GetPriorityClass (GetCurrentProcess ())
+ | CREATE_SUSPENDED), /* Creation flags. */
+ NULL, /* Environment. */
+ NULL, /* Use current drive/directory. */
+ &si, /* Startup information. */
+ &pi /* Returns process information. */
+ ))
+ {
+ TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_w32", ctx,
+ "CreateProcess failed: %s", w32_strerror (ctx, -1));
+ _assuan_free (cmdline);
+ if (nullfd != INVALID_HANDLE_VALUE)
+ CloseHandle (nullfd);
+
+ errno = EIO;
+ return -1;
+ }
+
+ _assuan_free (cmdline);
+ if (nullfd != INVALID_HANDLE_VALUE)
+ CloseHandle (nullfd);
+
+ ResumeThread (pi.hThread);
+ CloseHandle (pi.hThread);
+
+ /* _assuan_log_printf ("CreateProcess ready: hProcess=%p hThread=%p" */
+ /* " dwProcessID=%d dwThreadId=%d\n", */
+ /* pi.hProcess, pi.hThread, */
+ /* (int) pi.dwProcessId, (int) pi.dwThreadId); */
+
+ *r_pid = (pid_t) pi.hProcess;
+
+ /* No need to modify peer process, as we don't change the handle
+ names. However this also means we are not safe, as we inherit
+ too many handles. Should use approach similar to gpgme and glib
+ using a helper process. */
+
+ return 0;
+}
+
+#else
+
+static int
+writen (int fd, const char *buffer, size_t length)
+{
+ while (length)
+ {
+ int nwritten = write (fd, buffer, length);
+
+ if (nwritten < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ return -1; /* write error */
+ }
+ length -= nwritten;
+ buffer += nwritten;
+ }
+ return 0; /* okay */
+}
+
+
+int
+__assuan_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 pid;
+
+ pid = fork ();
+ if (pid < 0)
+ return -1;
+
+ if (pid == 0)
+ {
+ /* Child process (server side). */
+ int i;
+ int n;
+ char errbuf[512];
+ int *fdp;
+ int fdnul;
+
+ if (atfork)
+ atfork (atforkvalue, 0);
+
+ fdnul = open ("/dev/null", O_WRONLY);
+ if (fdnul == -1)
+ {
+ TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
+ "can't open `/dev/null': %s", strerror (errno));
+ _exit (4);
+ }
+
+ /* Dup handles to stdin/stdout. */
+ if (fd_out != STDOUT_FILENO)
+ {
+ if (dup2 (fd_out == ASSUAN_INVALID_FD ? fdnul : fd_out,
+ STDOUT_FILENO) == -1)
+ {
+ TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
+ "dup2 failed in child: %s", strerror (errno));
+ _exit (4);
+ }
+ }
+
+ if (fd_in != STDIN_FILENO)
+ {
+ if (dup2 (fd_in == ASSUAN_INVALID_FD ? fdnul : fd_in,
+ STDIN_FILENO) == -1)
+ {
+ TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
+ "dup2 failed in child: %s", strerror (errno));
+ _exit (4);
+ }
+ }
+
+ /* Dup stderr to /dev/null unless it is in the list of FDs to be
+ passed to the child. */
+ fdp = fd_child_list;
+ if (fdp)
+ {
+ for (; *fdp != -1 && *fdp != STDERR_FILENO; fdp++)
+ ;
+ }
+ if (!fdp || *fdp == -1)
+ {
+ if (dup2 (fdnul, STDERR_FILENO) == -1)
+ {
+ TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_unix", ctx,
+ "dup2(dev/null, 2) failed: %s", strerror (errno));
+ _exit (4);
+ }
+ }
+ close (fdnul);
+
+ /* Close all files which will not be duped and are not in the
+ fd_child_list. */
+ n = sysconf (_SC_OPEN_MAX);
+ if (n < 0)
+ n = MAX_OPEN_FDS;
+ for (i = 0; i < n; i++)
+ {
+ if (i == STDIN_FILENO || i == STDOUT_FILENO || i == STDERR_FILENO)
+ continue;
+ fdp = fd_child_list;
+ if (fdp)
+ {
+ while (*fdp != -1 && *fdp != i)
+ fdp++;
+ }
+
+ if (!(fdp && *fdp != -1))
+ close (i);
+ }
+ errno = 0;
+
+ if (! name)
+ {
+ /* No name and no args given, thus we don't do an exec
+ but continue the forked process. */
+ *argv = "server";
+
+ /* FIXME: Cleanup. */
+ return 0;
+ }
+
+ execv (name, (char *const *) argv);
+
+ /* oops - use the pipe to tell the parent about it */
+ snprintf (errbuf, sizeof(errbuf)-1,
+ "ERR %d can't exec `%s': %.50s\n",
+ _assuan_error (ctx, GPG_ERR_ASS_SERVER_START),
+ name, strerror (errno));
+ errbuf[sizeof(errbuf)-1] = 0;
+ writen (1, errbuf, strlen (errbuf));
+ _exit (4);
+ }
+
+ if (! name)
+ *argv = "client";
+
+ *r_pid = pid;
+
+ return 0;
+}
+#endif /* ! HAVE_W32_SYSTEM */
+
+
+/* Create a new process from NAME and ARGV. Provide FD_IN and FD_OUT
+ as stdin and stdout. Inherit the ASSUAN_INVALID_FD-terminated
+ FD_CHILD_LIST as given (no remapping), which must be inheritable.
+ On Unix, call ATFORK with ATFORKVALUE after fork and before exec. */
+int
+_assuan_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 res;
+ int i;
+ TRACE_BEG6 (ctx, ASSUAN_LOG_CTX, "_assuan_spawn", ctx,
+ "name=%s,fd_in=0x%x,fd_out=0x%x,"
+ "atfork=%p,atforkvalue=%p,flags=%i",
+ name ? name : "(null)", fd_in, fd_out,
+ atfork, atforkvalue, flags);
+
+ if (name)
+ {
+ i = 0;
+ while (argv[i])
+ {
+ TRACE_LOG2 ("argv[%2i] = %s", i, argv[i]);
+ i++;
+ }
+ }
+ i = 0;
+ while (fd_child_list[i] != ASSUAN_INVALID_FD)
+ {
+ TRACE_LOG2 ("fd_child_list[%2i] = 0x%x", i, fd_child_list[i]);
+ i++;
+ }
+
+ res = (ctx->system.spawn) (ctx, r_pid, name, argv, fd_in, fd_out,
+ fd_child_list, atfork, atforkvalue, flags);
+
+ if (name)
+ {
+ TRACE_LOG1 ("pid = 0x%x", *r_pid);
+ }
+ else
+ {
+ TRACE_LOG2 ("pid = 0x%x (%s)", *r_pid, *argv);
+ }
+
+ return TRACE_SYSERR (res);
+}
+
+
+/* FIXME: Add some sort of waitpid function that covers GPGME and
+ gpg-agent's use of assuan. */
+static pid_t
+__assuan_waitpid (assuan_context_t ctx, pid_t pid, int nowait,
+ int *status, int options)
+{
+#ifndef HAVE_W32_SYSTEM
+ /* 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 waitpid (pid, NULL, 0);
+#else /* ! HAVE_W32_SYSTEM */
+ CloseHandle ((HANDLE) pid);
+#endif /* HAVE_W32_SYSTEM */
+}
+
+
+pid_t
+_assuan_waitpid (assuan_context_t ctx, pid_t pid, int action,
+ int *status, int options)
+{
+ return (ctx->system.waitpid) (ctx, pid, action, status, options);
+}
+
+
+int
+__assuan_socketpair (assuan_context_t ctx, int namespace, int style,
+ int protocol, int filedes[2])
+{
+#if HAVE_W32_SYSTEM
+ errno = ENOSYS;
+ return -1;
+#else
+ return socketpair (namespace, style, protocol, filedes);
+#endif
+}
+
+int
+_assuan_socketpair (assuan_context_t ctx, int namespace, int style,
+ int protocol, assuan_fd_t filedes[2])
+{
+ int res;
+ TRACE_BEG4 (ctx, ASSUAN_LOG_SYSIO, "_assuan_socketpair", ctx,
+ "namespace=%i,style=%i,protocol=%i,filedes=%p",
+ namespace, style, protocol, filedes);
+
+ res = (ctx->system.socketpair) (ctx, namespace, style, protocol, filedes);
+ if (res == 0)
+ TRACE_LOG2 ("filedes = { 0x%x, 0x%x }", filedes[0], filedes[1]);
+
+ return TRACE_SYSERR (res);
+}
+
+
+/* The default system hooks for assuan contexts. */
+struct assuan_system_hooks _assuan_system_hooks =
+ {
+ ASSUAN_SYSTEM_HOOKS_VERSION,
+ __assuan_usleep,
+ __assuan_pipe,
+ __assuan_close,
+ __assuan_read,
+ __assuan_write,
+ __assuan_recvmsg,
+ __assuan_sendmsg,
+ __assuan_spawn,
+ __assuan_waitpid,
+ __assuan_socketpair
+ };