[svn] assuan - r309 - in trunk: . doc src

svn author marcus cvs at cvs.gnupg.org
Fri Oct 16 20:24:47 CEST 2009


Author: marcus
Date: 2009-10-16 20:24:46 +0200 (Fri, 16 Oct 2009)
New Revision: 309

Removed:
   trunk/src/assuan-io-pth.c
Modified:
   trunk/ChangeLog
   trunk/NEWS
   trunk/autogen.sh
   trunk/configure.ac
   trunk/doc/ChangeLog
   trunk/doc/assuan.texi
   trunk/src/ChangeLog
   trunk/src/Makefile.am
   trunk/src/assuan-buffer.c
   trunk/src/assuan-client.c
   trunk/src/assuan-defs.h
   trunk/src/assuan-error.c
   trunk/src/assuan-handler.c
   trunk/src/assuan-inquire.c
   trunk/src/assuan-io.c
   trunk/src/assuan-listen.c
   trunk/src/assuan-pipe-connect.c
   trunk/src/assuan-pipe-server.c
   trunk/src/assuan-socket-connect.c
   trunk/src/assuan-socket-server.c
   trunk/src/assuan-socket.c
   trunk/src/assuan-uds.c
   trunk/src/assuan.c
   trunk/src/assuan.h
   trunk/src/context.c
   trunk/src/conversion.c
   trunk/src/debug.h
   trunk/src/libassuan-config.in
   trunk/src/libassuan.def
   trunk/src/libassuan.m4
   trunk/src/libassuan.vers
   trunk/src/system.c
Log:
2009-10-16  Marcus Brinkmann  <marcus at 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 at g10code.com>

	* assuan.texi: Remove documentation for thread support.
	(assuan_pipe_connect_ext): Update prototype.

src/
2009-10-16  Marcus Brinkmann  <marcus at 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.


[The diff below has been truncated]

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2009-10-14 11:27:08 UTC (rev 308)
+++ trunk/ChangeLog	2009-10-16 18:24:46 UTC (rev 309)
@@ -1,3 +1,12 @@
+2009-10-16  Marcus Brinkmann  <marcus at 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 at g10code.de>
 
 	* configure.ac: AC_REPLACE_FUNCS for vasprintf.

Modified: trunk/doc/ChangeLog
===================================================================
--- trunk/doc/ChangeLog	2009-10-14 11:27:08 UTC (rev 308)
+++ trunk/doc/ChangeLog	2009-10-16 18:24:46 UTC (rev 309)
@@ -1,3 +1,8 @@
+2009-10-16  Marcus Brinkmann  <marcus at g10code.com>
+
+	* assuan.texi: Remove documentation for thread support.
+	(assuan_pipe_connect_ext): Update prototype.
+
 2009-10-14  Werner Koch  <wk at g10code.com>
 
 	* assuan.texi (Utilities): Describe assuan_get_command_name.

Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog	2009-10-14 11:27:08 UTC (rev 308)
+++ trunk/src/ChangeLog	2009-10-16 18:24:46 UTC (rev 309)
@@ -1,3 +1,105 @@
+2009-10-16  Marcus Brinkmann  <marcus at 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 at g10code.com>
 
 	* assuan-defs.h (assuan_context_s): Add field CURRENT_CMD_NAME.
@@ -7,6 +109,18 @@
 
 2009-10-08  Marcus Brinkmann  <marcus at 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 at g10code.de>
+
 	* assuan.h (assuan_get_assuan_log_stream,
 	assuan_set_assuan_log_stream): Remove prototypes.
 	* libassuan.def: Remove assuan_get_assuan_log_stream,

Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2009-10-14 11:27:08 UTC (rev 308)
+++ trunk/NEWS	2009-10-16 18:24:46 UTC (rev 309)
@@ -13,8 +13,12 @@
    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:
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 _ASSUAN_ONLY_GPG_ERRORS        REMOVED
@@ -51,6 +55,18 @@
 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
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 

Modified: trunk/autogen.sh
===================================================================
--- trunk/autogen.sh	2009-10-14 11:27:08 UTC (rev 308)
+++ trunk/autogen.sh	2009-10-16 18:24:46 UTC (rev 309)
@@ -77,7 +77,6 @@
 
     ./configure --enable-maintainer-mode  --prefix=${w32root}  \
             --host=${host} --build=${build} \
-            --with-pth-prefix=${w32root} \
             --disable-shared    
 
     exit $?

Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac	2009-10-14 11:27:08 UTC (rev 308)
+++ trunk/configure.ac	2009-10-16 18:24:46 UTC (rev 309)
@@ -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 @@
 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,13 +181,7 @@
 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,
 	[NETLIBS="-lsocket $NETLIBS"]))
@@ -211,10 +195,6 @@
 # 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 @@
 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.

Modified: trunk/doc/assuan.texi
===================================================================
--- trunk/doc/assuan.texi	2009-10-14 11:27:08 UTC (rev 308)
+++ trunk/doc/assuan.texi	2009-10-16 18:24:46 UTC (rev 309)
@@ -465,11 +465,7 @@
 gcc -o foo foo.c $(libassuan-config --cflags --libs)
 @end example
 
-If your application uses Pth or pthread, you need to pass the option
- at 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 @@
 LDADD = $(LIBASSUAN_LIBS)
 @end example
 
- at 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}
- at 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.
- at end defmac
 
- at 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}
- at 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.
- at 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
+ at code{assuan_set_gpg_err_source}, @code{assuan_set_malloc_hooks} and
+ at code{assuan_set_log_cb} should not be called concurrently with
+ at 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.
+ at item If you have callback functions shared by multiple functions,
+the callback function must be reentrant for that purpose.
+ at code{libassuan} does not serialize invocation of callback functions
+across contexts.
 @end itemize
 
 
@@ -950,12 +937,12 @@
 sockets, the full-fledged variant of the above function should be
 used:
 
- at deftypefun gpg_error_t assuan_pipe_connect_ext (@w{assuan_context_t *@var{ctx}}, at 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}})
+ at deftypefun gpg_error_t assuan_pipe_connect_ext (@w{assuan_context_t *@var{ctx}}, at 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

Modified: trunk/src/Makefile.am
===================================================================
--- trunk/src/Makefile.am	2009-10-14 11:27:08 UTC (rev 308)
+++ trunk/src/Makefile.am	2009-10-16 18:24:46 UTC (rev 309)
@@ -21,16 +21,10 @@
              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_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
-

Modified: trunk/src/assuan-buffer.c
===================================================================
--- trunk/src/assuan-buffer.c	2009-10-14 11:27:08 UTC (rev 308)
+++ trunk/src/assuan-buffer.c	2009-10-16 18:24:46 UTC (rev 309)
@@ -37,7 +37,7 @@
 {
   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 @@
   *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 @@
     {
       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 @@
   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);
 }

Modified: trunk/src/assuan-client.c
===================================================================
--- trunk/src/assuan-client.c	2009-10-14 11:27:08 UTC (rev 308)
+++ trunk/src/assuan-client.c	2009-10-16 18:24:46 UTC (rev 309)
@@ -49,7 +49,7 @@
 	{
 	  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;

Modified: trunk/src/assuan-defs.h
===================================================================
--- trunk/src/assuan-defs.h	2009-10-14 11:27:08 UTC (rev 308)
+++ trunk/src/assuan-defs.h	2009-10-16 18:24:46 UTC (rev 309)
@@ -56,19 +56,6 @@
 };
 
 
-/* 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 @@
   {
     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 @@
 
   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_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 @@
 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 @@
 
 
 /*-- 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 --*/
 
-
-/*-- 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

Modified: trunk/src/assuan-error.c
===================================================================
--- trunk/src/assuan-error.c	2009-10-14 11:27:08 UTC (rev 308)
+++ trunk/src/assuan-error.c	2009-10-16 18:24:46 UTC (rev 309)
@@ -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;

Modified: trunk/src/assuan-handler.c
===================================================================
--- trunk/src/assuan-handler.c	2009-10-14 11:27:08 UTC (rev 308)
+++ trunk/src/assuan-handler.c	2009-10-16 18:24:46 UTC (rev 309)
@@ -219,6 +219,7 @@
   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 @@
 }
 
 
-
-  
-
 /* 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 @@
      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 @@
     {
       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)

Modified: trunk/src/assuan-inquire.c
===================================================================
--- trunk/src/assuan-inquire.c	2009-10-14 11:27:08 UTC (rev 308)
+++ trunk/src/assuan-inquire.c	2009-10-16 18:24:46 UTC (rev 309)
@@ -176,7 +176,7 @@
         {
 	  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;

Deleted: trunk/src/assuan-io-pth.c

Modified: trunk/src/assuan-io.c
===================================================================
--- trunk/src/assuan-io.c	2009-10-14 11:27:08 UTC (rev 308)
+++ trunk/src/assuan-io.c	2009-10-16 18:24:46 UTC (rev 309)
@@ -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
-    }
-}
-

Modified: trunk/src/assuan-listen.c
===================================================================
--- trunk/src/assuan-listen.c	2009-10-14 11:27:08 UTC (rev 308)
+++ trunk/src/assuan-listen.c	2009-10-16 18:24:46 UTC (rev 309)
@@ -138,7 +138,7 @@
 {
   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 @@
   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;
 }

Modified: trunk/src/assuan-pipe-connect.c
===================================================================
--- trunk/src/assuan-pipe-connect.c	2009-10-14 11:27:08 UTC (rev 308)
+++ trunk/src/assuan-pipe-connect.c	2009-10-16 18:24:46 UTC (rev 309)
@@ -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 @@
       /* 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 @@
   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;
+  /* Close the stdin/stdout child fds in the parent.  */
+  _assuan_close (ctx, rp[1]);
+  _assuan_close (ctx, wp[0]);
 
-      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]);
-
-  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,177 +237,134 @@
     _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)
-    {
-#ifdef _ASSUAN_USE_DOUBLE_FORK      
-      pid_t pid2;
+  /* 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 ((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
+  /* If this is the server child process, exit early.  */
+  if (! name && (*argv)[0] == 's')
+    {
+      _assuan_free (ctx, child_fds);
+      _assuan_close (ctx, fds[0]);
+      return 0;
     }
 
-  if (! name)
-    *argv = "client";
+  _assuan_close (ctx, fds[1]);
 
-#ifdef _ASSUAN_USE_DOUBLE_FORK
-  _assuan_waitpid (pid, NULL, 0);
-  pid = -1;
-#endif
-
-  close (fds[1]);
-
   ctx->pipe_mode = 1;
   ctx->inbound.fd  = fds[0]; 
   ctx->outbound.fd = fds[0]; 
@@ -535,282 +379,6 @@
 }
 #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))




More information about the Gnupg-commits mailing list