[Pkg-gnupg-commit] [libassuan] 248/437: 2009-09-19 Marcus Brinkmann <marcus at g10code.de>

Eric Dorland eric at moszumanska.debian.org
Fri May 22 05:33:49 UTC 2015


This is an automated email from the git hooks/post-receive script.

eric pushed a commit to branch master
in repository libassuan.

commit cd87e56dac64c74d45f42838fc1049848f8aadcd
Author: Marcus Brinkmann <mb at g10code.com>
Date:   Mon Sep 21 01:08:08 2009 +0000

    2009-09-19  Marcus Brinkmann  <marcus at g10code.de>
    
    	* tests/fdpassing.c: Update to new API.
    	* configure.ac: Check for stdint.h and inttypes.h.  Invoke
    	AC_TYPE_UINTPTR_T.
    
    doc/
    2009-09-21  Marcus Brinkmann  <marcus at g10code.de>
    
    	* assuan.texi: Update to new API.
    
    src/
    2009-09-19  Marcus Brinkmann  <marcus at g10code.de>
    
    	* src/libassuan.vers, src/libassuan.def: Update to new API.
    	* assuan.c, context.c, system.c, debug.c: New files.
    	* Makefile.am (common_sources): Add assuan.c, context.c, system.c
    	and debug.c.
    	* assuan.h: Include <stdarg.h>.  Fix inclusion of <gpg-error.h>.
    	(_ASSUAN_EXT_SYM_PREFIX, _ASSUAN_PREFIX1, _ASSUAN_PREFIX2)
    	(_ASSUAN_PREFIX): Remove support for renaming the whole library,
    	now that we have a stable shared library interface that can evolve
    	to cover all needs (particularly those of GPGME).
    	(assuan_malloc_hooks, assuan_malloc_hooks_t, assuan_log_cb_t)
    	(assuan_io_monitor_t): New types.
    	(ASSUAN_LOG_INIT, ASSUAN_LOG_CTX, ASSUAN_LOG_ENGINE)
    	(ASSUAN_LOG_DATA, ASSUAN_LOG_SYSIO, ASSUAN_IO_FROM_PEER)
    	(ASSUAN_IO_TO_PEER, ASSUAN_IO_MONITOR_NOLOG)
    	(ASSUAN_IO_MONITOR_IGNORE): New symbols.
    	(assuan_set_gpg_err_source, assuan_get_gpg_err_source)
    	(assuan_get_malloc_hooks, assuan_set_log_cb, assuan_get_log_cb)
    	(assuan_new, assuan_new_ext, assuan_release): New function
    	prototypes.
    	(assuan_init_pipe_server, assuan_init_socket_server)
    	(assuan_init_socket_server_ext, assuan_pipe_connect)
    	(assuan_pipe_connect_ext, assuan_socket_connect)
    	(assuan_socket_connect_ext): Take a context argument instead of
    	pointer to context.
    	(assuan_deinit_server, assuan_disconnect)
    	(assuan_set_assuan_err_source): Remove function prototypes.
    	* assuan-defs.h (ASSUAN_GCC_A_PURE): Moved here from XXX
    	(_assuan_error): New macro.
    	(struct assuan_context_s): New members err_source, w32_strerror,
    	malloc_hooks, log_cb, log_cb_data: New members.  Move confidential
    	into flags.  New member engine.
    	(_assuan_log_handler, _assuan_error_default, _assuan_disconnect):
    	New prototypes.
    	(_assuan_new_context): Remove prototype.
    	(_assuan_malloc, _assuan_calloc, _assuan_realloc, _assuan_free):
    	Add context argument to prototype.
    	* assuan-util.c (alloc_func, realloc_func, free_func): Remove
    	global variables.
    	(assuan_set_malloc_hooks, _assuan_malloc, _assuan_realloc)
    	(_assuan_calloc, _assuan_free, assuan_set_pointer)
    	(assuan_get_pointer, assuan_begin_confidential)
    	(assuan_end_confidential, assuan_set_io_monitor, assuan_set_flag)
    	(assuan_get_flag): Move functions to ...
    	* assuan-client.c: Add ctx argument to all invocations of
    	_assuan_error.
    	* assuan-socket-server.c, assuan-socket-connect.c,
    	assuan-connect.c: Likewise.
    	* assuan-buffer.c: Likewise.  Also update access to confidential
    	flag.
    	* assuan-uds.c: Add ctx argument to all invocations of
    	_assuan_malloc, _assuan_realloc, _assuan_calloc, _assuan_free and
    	_assuan_error.
    	* assuan_listen.c, assuan-inquire.c, assuan-handler.c: Likewise.
    	* assuan-error.c (err_source): Remove global variable.
    	(assuan_set_assuan_err_source): Removed function.
    	(_assuan_w32_strerror): Moved here from assuan-logging.c and made
    	thread-safe.
    	(_assuan_error): Removed function (is now macro).
    	* assuan-handler.c: Update access to confidential flag.
    	* assuan-socket-server.c (accept_connection_bottom): Update access
    	to confidential flag in context.
    	(assuan_init_socket_server, assuan_init_socket_server_ext): Take
    	ctx argument instead of pointer to ctx.
    	* assuan-inquire.c (init_membuf, put_membuf, get_membuf)
    	(free_membuf): Take context argument and change all callers.
    	* assuan-socket-server.c (assuan_socket_connect)
    	(assuan_socket_connect_ext): Take ctx argument instead of pointer
    	to ctx.
    	* assuan-pipe-connect.c (initial_handshake, pipe_connect_unix)
    	(socketpair_connect, assuan_pipe_connect)
    	(assuan_pipe_connect_ext): Likewise.
    	(socketpair_connect): Now that ctx is not a pointer argument
    	anymore, return if we are server or client in the argv argument.
    	* assuan-logging.c (_assuan_log_handler): New function.
    	(_assuan_w32_strerror): Move to assuan-error.c
    	* assuan-connect.c (assuan_disconnect): Renamed to ...
    	(_assuan_disconnect): ... this.
    	* assuan-pipe-server.c (_assuan_new_context): Removed function.
    	(assuan_init_pipe_server): Take ctx argument instead of pointer to
    	ctx.
    	(_assuan_release_context): Removed function.
    	(_assuan_deinit_server): Reimplement.
---
 ChangeLog                   |   6 +
 NEWS                        |  54 ++++--
 TODO                        |   3 +-
 configure.ac                |   3 +-
 doc/ChangeLog               |   4 +
 doc/assuan.texi             | 439 ++++++++++++++++++++++++++++++--------------
 src/ChangeLog               |  87 ++++++++-
 src/Makefile.am             |   6 +-
 src/assuan-buffer.c         |  86 ++++-----
 src/assuan-client.c         |   8 +-
 src/assuan-connect.c        |  28 +--
 src/assuan-defs.h           | 125 ++++++++-----
 src/assuan-error.c          |  41 ++---
 src/assuan-handler.c        |  55 +++---
 src/assuan-inquire.c        |  74 ++++----
 src/assuan-io-pth.c         |  23 ---
 src/assuan-io.c             |  25 ---
 src/assuan-listen.c         |  16 +-
 src/assuan-logging.c        | 156 ++++------------
 src/assuan-pipe-connect.c   | 281 ++++++++++++++--------------
 src/assuan-pipe-server.c    | 180 ++++++++----------
 src/assuan-socket-connect.c |  92 +++++-----
 src/assuan-socket-server.c  |  57 +++---
 src/assuan-uds.c            |  27 +--
 src/assuan-util.c           | 190 -------------------
 src/assuan.c                | 177 ++++++++++++++++++
 src/assuan.h                | 377 +++++++++++++++----------------------
 src/context.c               | 127 +++++++++++++
 src/conversion.c            | 116 ++++++++++++
 src/debug.c                 | 179 ++++++++++++++++++
 src/debug.h                 | 260 ++++++++++++++++++++++++++
 src/libassuan.def           | 120 ++++++------
 src/libassuan.vers          |  14 +-
 src/system.c                |  72 ++++++++
 tests/fdpassing.c           |  32 ++--
 35 files changed, 2205 insertions(+), 1335 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b7768d9..749ef09 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2009-09-19  Marcus Brinkmann  <marcus at g10code.de>
+
+	* tests/fdpassing.c: Update to new API.
+	* configure.ac: Check for stdint.h and inttypes.h.  Invoke
+	AC_TYPE_UINTPTR_T.
+
 2009-09-08  Marcus Brinkmann  <marcus at g10code.de>
 
 	* m4/gpg-error.m4: New file.
diff --git a/NEWS b/NEWS
index 1ad09af..9d72701 100644
--- a/NEWS
+++ b/NEWS
@@ -1,23 +1,55 @@
-Noteworthy changes in version 1.1.0
+Noteworthy changes in version 1.1.0 (unreleased)
 ------------------------------------------------
 
  * Now using libtool and builds a DSO. 
 
  * Lots of interface cleanups.  See below for details of the most
-   important changes.
+   important changes.  Here is a quick note on how to upgrade:
+
+   For each invocation of the connect or server functions, allocate a
+   context with assuan_new and use that.  Instead of assuan_disconnect
+   or assuan_deinit_server, call assuan_release.  Use
+   assuan_set_gpg_err_source instead of assuan_set_assuan_err_source.
+   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().
 
  * Interface changes relative to the 1.0.5 release:
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-_ASSUAN_ONLY_GPG_ERRORS        Removed.
-assuan_init_connected_socket_server Removed.
-assuan_strerror		       Removed.
-assuan_pipe_connect2           Removed.
+_ASSUAN_ONLY_GPG_ERRORS        REMOVED
+assuan_set_assuan_err_source   REMOVED: Use assuan_set_gpg_err_source.
+assuan_set_gpg_err_source      NEW
+assuan_get_gpg_err_source      NEW
+assuan_strerror		       REMOVED
 ASSUAN_*		       Error values removed.
-assuan_error_t		       Removed.
-AssuanError		       Removed.
-AssuanCommand		       Removed.
-assuan_flag_t		       Changed from enum to unsigned int.
-ASSUAN_CONTENT		       Removed.
+assuan_error_t		       REMOVED
+AssuanError		       REMOVED
+assuan_init_connected_socket_server REMOVED
+assuan_pipe_connect2           REMOVED
+AssuanCommand		       REMOVED
+assuan_flag_t		       CHANGED: From enum to unsigned int.
+ASSUAN_CONTENT		       REMOVED
+assuan_disconnect	       REMOVED: Use assuan_release.
+assuan_deinit_server           REMOVED: Use assuan_release.
+assuan_get_malloc_hooks        NEW
+assuan_set_log_cb              NEW
+assuan_get_log_cb              NEW
+assuan_new_ext                 NEW
+assuan_new                     NEW
+assuan_release                 NEW
+assuan_init_socket_server      CHANGED: Take ctx arg instead of pointer to ctx.
+assuan_init_socket_server_ext  CHANGED: Take ctx arg instead of pointer to ctx.
+assuan_socket_connect          CHANGED: Take ctx arg instead of pointer to ctx.
+assuan_socket_connect_ext      CHANGED: Take ctx arg instead of pointer to ctx.
+assuan_pipe_connect            CHANGED: Take ctx arg instead of pointer to ctx.
+			       If NAME is NULL, ARGV will contain fork result.
+assuan_pipe_connect_ext        CHANGED: Take ctx arg instead of pointer to ctx.
+			       If NAME is NULL, ARGV will contain fork result.
+assuan_init_pipe_server        CHANGED: Take ctx arg instead of pointer to ctx.
+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.
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Noteworthy changes in version 1.0.5 (2008-05-25)
diff --git a/TODO b/TODO
index 7cfca85..b759c14 100644
--- a/TODO
+++ b/TODO
@@ -2,13 +2,14 @@
 * Check that we have Pth-ed all blocking fucntions.
 * When turning libassuan into a shared library, provide a general
   version as well as a Pth-enabled one.
+* Even better, allow replacing all these I/O and spawn functions on
+  a per-context basis at runtime (like the old assuan_set_io_hooks but better).
 * assuan_transact returns immediately on an error in the callback
   function.  It might be better to return the error to the caller. As
   an example see dirmngr-client, where we need to send empty responses
   for unknown inquiries, albeit dirmngr itself would handle the
   returns for assuan_inquire gracefully.  We need to check all
   applications whether it is safe to change this.
-
 * XOPEN_SOURCE and snprintf
   See Peter O'Gorman's mail.
 
diff --git a/configure.ac b/configure.ac
index 381d317..4bc5f85 100644
--- a/configure.ac
+++ b/configure.ac
@@ -227,7 +227,8 @@ AC_SUBST(LIBASSUAN_CONFIG_EXTRA_LIBS)
 
 # Checks for header files.
 AC_HEADER_STDC
-AC_CHECK_HEADERS([string.h locale.h sys/uio.h])
+AC_CHECK_HEADERS([string.h locale.h sys/uio.h stdint.h inttypes.h])
+AC_TYPE_UINTPTR_T
 
 # Checks for typedefs, structures, and compiler characteristics.
 AC_C_CONST
diff --git a/doc/ChangeLog b/doc/ChangeLog
index b9e6e94..95441d5 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,7 @@
+2009-09-21  Marcus Brinkmann  <marcus at g10code.de>
+
+	* assuan.texi: Update to new API.
+
 2009-09-01  Marcus Brinkmann  <marcus at g10code.de>
 
 	* assuan.texi: (External I/O Loop Server): Document
diff --git a/doc/assuan.texi b/doc/assuan.texi
index 67ba8b3..a3ec0a3 100644
--- a/doc/assuan.texi
+++ b/doc/assuan.texi
@@ -374,7 +374,7 @@ No operation.  Returns OK without any action.
 Libassuan is used with gpg-error style error codes.  It is recommended
 to set the error source to a different value than the default
 @code{GPG_ERR_SOURCE_UNKNOWN} by calling @ref{function
-assuan_set_assuan_err_source} early.
+assuan_set_gpg_err_source} early.
 
 
 @c 
@@ -428,7 +428,7 @@ directory in which the header file is located to the compilers include
 file search path (via the @option{-I} option).
 
 However, the path to the include file is determined at the time the
-source is configured.  To solve this problem, @sc{libgcrypt} ships with
+source is configured.  To solve this problem, @code{libassuan} ships with
 a small helper program @command{libassuan-config} that knows the path to
 the include file and other configuration options.  The options that need
 to be added to the compiler invocation at compile time are output by the
@@ -519,14 +519,15 @@ compiler and linker.
 @node Multi Threading
 @section Multi Threading
 
-The @sc{libgcrypt} library is thread-safe if you adhere to the following
+The @code{libassuan} library is thread-safe if you adhere to the following
 requirements:
 
 @itemize @bullet
 @item Run the initialization functions before you actually start
 to use threads.
 @item Only one thread at a time may access an @code{libassuan} context.
- at item Use @code{assuan_set_assuan_log_stream} to setup a default log stream.
+ at item If you use the default log handler, use
+ at code{assuan_set_assuan_log_stream} to setup a default log stream.
 @end itemize
 
 
@@ -537,9 +538,11 @@ to use threads.
 @chapter Generalities
 
 @menu
-* Data Types::                  Data types used by @code{libassuan}.
-* Initializing the library::    How to initialize the library.
-* Reading and Writing::         How to communicate with the peer.
+* Data Types:: Data types used by @code{libassuan}.
+* Initializing the library:: How to initialize the library.
+* Default Log Handler:: How to configure the default log handler.
+* Contexts:: How to work with contexts.
+* Reading and Writing:: How to communicate with the peer.
 @end menu
 
 
@@ -548,14 +551,14 @@ to use threads.
 @section Data Types used by the library
 
 @sc{Assuan} uses a context to keep the state for a connection.  The
-following data type is used ace:
+following data type is used for that:
 
 @deftp {Data type} assuan_context_t
 The @code{assuan_context_t} type is a pointer to an object maintained
-internally by the library.  Certain @sc{Assuan} functions allocate
-such a context and return it to the caller using this data type. Other
-functions take this data type to access the state created by these
-functions.
+internally by the library.  Contexts are allocated with
+ at code{assuan_new} or @code{assuan_new_ext} and released with
+ at code{assuan_release}.  Other functions take this data type to access
+the state created by these functions.
 @end deftp
 
 
@@ -574,23 +577,139 @@ some initialization hooks provided which are often useful.  These
 should be called as early as possible and in a multi-threaded
 application before a second thread is created. 
 
+These functions initialize default values that are used at context
+creation with @code{assuan_new}.  As there can only be one default,
+all values can also be set directly with @code{assuan_new_ext} or with
+context-specific functions after context creation.
+
 If your application uses its own memory allocation functions or wrappers
 it is good idea to tell @code{libassuan} about it so it can make use of the
-same functions or wrappers.  You do this with
+same functions or wrappers:
+
+ at deftp {Data type} {struct assuan_malloc_hooks}
+This structure is used to store the memory allocation callback
+interface functions.  It has the following members, whose semantics
+are identical to the corresponding system functions:
+
+ at table @code
+ at item void *(*malloc) (size_t cnt)
+This is the function called by @sc{Assuan} to allocate memory for a context.
+
+ at item void *(*realloc) (void *ptr, size_t cnt)
+This is the function called by @sc{Assuan} to reallocate memory for a context.
+
+ at item void (*free) (void *ptr)
+This is the function called by @sc{Assuan} to release memory for a context.
+ at end table
+ at end deftp
+
+ at deftp {Data type} {assuan_malloc_hooks_t}
+This is a pointer to a @code{struct assuan_malloc_hooks}.
+ at end deftp
+
+/* Get the default malloc hooks.  */
+assuan_malloc_hooks_t assuan_get_malloc_hooks (void);
+
+ at deftypefun void assuan_set_malloc_hooks (@w{assuan_malloc_hooks_t @var{malloc_hooks}})
+This function sets the default allocation hooks for new contexts
+allocated with @code{assuan_new}.  You need to provide all three
+functions.  Those functions need to behave exactly as their standard
+counterparts @code{malloc}, @code{realloc} and @code{free}.  If you
+write your own functions, please take care to set @code{errno}
+whenever an error has occurred.
+ at end deftypefun
+
+ at deftypefun assuan_malloc_hooks_t assuan_get_malloc_hooks ()
+This function gets the default allocation hooks for new contexts
+allocated with @code{assuan_new}.  The result structure is statically
+allocated and should not be modified.
+ at end deftypefun
 
- at deftypefun void assuan_set_malloc_hooks (@w{void *(*@var{malloc_func})(size_t)}, @w{void *(*@var{realloc_func})(void *, size_t)}, @w{void (*@var{free_func})(void*)})
-You need to provide all three functions.  Those functions need to behave
-exactly as their standard counterparts (@code{malloc}, @code{realloc}
-and @code{free}).  If you write your own functions, please take care to
-set @code{errno} whenever an error has occurred.
+The @sc{Assuan} library uses @code{libgpg-error} error values, which
+consist and error code and an error source.  The default source used
+by contexts allocated with @code{assuan_new} can be set with the
+following function.
+
+ at anchor{function assuan_set_gpg_err_source}
+ at deftypefun void assuan_set_gpg_err_source (@w{gpg_err_source_t @var{err_source}})
+This function sets the default error source for errors generated by
+contexts allocated with @code{assuan_new}.
+
+One way to call this function is
+ at smallexample
+assuan_set_assuan_err_source (GPG_ERR_SOURCE_DEFAULT);
+ at end smallexample
+ at end deftypefun
+
+ at deftypefun gpg_err_source_t assuan_get_gpg_err_source (void)
+This function gets the default error source for errors generated by
+contexts allocated with @code{assuan_new}.
 @end deftypefun
 
 @noindent
 To integrate assuan logging and diagnostics into your own logging
 system, you may use the following two functions:
 
+ at deftp {Data type} {int (*assuan_log_cb_t) (@w{assuan_context_t @var{ctx}}, @w{void *@var{hook_value}}, @w{unsigned int @var{cat}}, @w{const char *@var{msg}})}
+The user-provided callback function takes a context @var{ctx}, for
+which the message @var{msg} was generated, and a hook value
+ at var{hook_value} that was supplied when the log handler was registered
+for the context with @code{assuan_set_log_cb}, and a category
+ at var{cat}.  The category is one of:
+
+ at table @code
+ at item ASSUAN_LOG_INIT
+ at item ASSUAN_LOG_CTX
+ at item ASSUAN_LOG_ENGINE
+ at item ASSUAN_LOG_DATA
+ at item ASSUAN_LOG_SYSIO
+ at end table
+
+The user may then, depending on the category, write the message to a
+log file or treat it in some other way.
+
+If @var{msg} is a null pointer, then no message should be logged, but
+the function should return 1 if it is interested in log messages with
+the category @var{cat}.  If it is not interested, 0 should be
+returned.  This allows @code{libassuan} to suppress the generation of
+expensive debug output.
+ at end deftp
+
+ at deftypefun void assuan_set_log_cb (@w{assuan_log_cb_t @var{log_cb}}, @w{void *@var{log_cb_data}})
+This function sets the default logging handler for log messages
+generated by contexts allocated with @code{assuan_new}.
+ at end deftypefun
+
+ at deftypefun void assuan_get_log_cb (@w{assuan_log_cb_t *@var{log_cb}}, @w{void **@var{log_cb_data}})
+This function gets the default logging handler for log messages
+generated by contexts allocated with @code{assuan_new}.
+ at end deftypefun
+
+You do not need to set a log handler, as @sc{Assuan} provides a
+configurable default log handler that should be suitable for most
+purposes.  Logging can be disabled completely by setting the log
+handler to a null pointer.
+
+ at node Default Log Handler
+ at section Default Log Handler
+
+The default log handler can be configured by the following functions:
+
+ at deftypefun void assuan_set_assuan_log_prefix (@w{const char *@var{text}})
+Set the prefix to be used at the start of a line emitted by assuan
+on the log stream to @var{text}.  The default is the empty string. 
+ at end deftypefun
+
+
+ at deftypefun @w{const char *} assuan_get_assuan_log_prefix (void)
+Return the prefix to be used at the start of a line emitted by assuan
+on the log stream.  The default implementation returns the empty
+string.
+ at end deftypefun
+
+
 @deftypefun void assuan_set_assuan_log_stream (FILE *@var{fp})
-This sets the stream to which @code{libassuan} should log messages not
+This sets the default log stream to which @code{libassuan} should log messages not
 associated with a specific context to @var{fp}.  The default is to log
 to @code{stderr}.  This default value is also changed by using
 @code{assuan_set_log_stream} (to set a logging stream for a specific
@@ -599,21 +718,145 @@ thread-safe and thus it is highly recommended to use this function to
 setup a proper default.
 @end deftypefun
 
- at deftypefun void assuan_set_assuan_log_prefix (@w{const char *@var{text}})
-Set the prefix to be used at the start of a line emitted by assuan
-on the log stream to @var{text}.  The default is the empty string. 
+
+ at deftypefun @w{FILE *} assuan_get_assuan_log_stream (void)
+Return the stream which is currently being using for global logging.
 @end deftypefun
 
- at anchor{function assuan_set_assuan_err_source}
- at deftypefun void assuan_set_assuan_err_source (@w{int @var{errsource}})
-Set the error source for error values generated by @code{libassuan}.
- at var{errsource} is one of the @code{libgpg-error} sources.  The usual
-way to call this function is
+The log stream used by the default log handler can also be set on a
+per context basis.
+
+ at deftypefun void assuan_set_log_stream (@w{assuan_context_t @var{ctx}}, @w{FILE *@var{fp}})
+Enable debugging for the context @var{ctx} and write all debugging
+output to the stdio stream @var{fp}.  If the default log stream (used
+for non-context specific events) has not yet been set, a call to this
+functions implicitly sets this stream also to @var{fp}.
+ at end deftypefun
+
+
+ at node Contexts
+ at section How to work with contexts
+
+Some operations work globally on the library, but most operate in a
+context, which saves state across operations.  To allow the use of
+ at code{libassuan} in mixed environments, such as in a library using
+GPGME and an application using GPGME, the context is very extensive
+and covers utilitary information like memory allocation callbacks as
+well as specific information associated with client/server operations.
+
+ at deftypefun gpg_error_t assuan_new (@w{assuan_context_t *@var{ctx_p}})
+The function @code{assuan_new} creates a new context, using the global
+default memory allocation, log handler and @code{libgpg-error} source.
+It is equivalent to
+
 @smallexample
-assuan_set_assuan_err_source (GPG_ERR_SOURCE_DEFAULT);
+gpg_error_t err;
+assuan_log_cb_t log_cb;
+void *log_cb_data;
+
+assuan_get_log_cb (&log_cb, &log_cb_data);
+err = assuan_new_ext (ctx_p, assuan_get_gpg_err_source (),
+                      assuan_get_malloc_hooks (), log_cb, log_cb_data);
+ at end smallexample
+
+As you can see, this is not thread-safe.  Take care not to modify the
+memory allocation hooks or log callback handler concurrently with
+ at code{assuan_new}.
+
+The function returns an error if a memory allocation error occurs, and
+0 with the new context in @var{ctx_p} otherwise.
+ at end deftypefun
+
+ at deftypefun gpg_error_t assuan_new_ext (@w{assuan_context_t *@var{ctx_p}}, @w{gpg_err_source_t @var{err_source}}, @w{assuan_malloc_hooks_t @var{malloc_hooks}}, @w{assuan_log_cb_t @var{log_cb}}, @w{void *@var{log_cb_data}})
+The function @code{assuan_new_ext} creates a new context using the
+supplied @code{libgpg-error} error source @var{err_source}, the memory
+allocation hooks @var{malloc_hooks} and the log handler @var{log_cb}
+with the user data @var{log_cb_data}.
+ at end deftypefun
+
+After the context has been used, it can be destroyed again.
+
+ at deftypefun void assuan_release (assuan_context_t ctx)
+The function @code{assuan_release} destroys the context CTX and
+releases all associated resources.
+ at end deftypefun
+
+Other properties of the context beside the memory allocation handler,
+the log handler, and the @code{libgpg-error} source can be set after
+context creation.  Here are some of them:
+
+ at deftypefun void assuan_set_pointer (@w{assuan_context_t @var{ctx}}, @w{void *@var{pointer}})
+
+Store the arbitrary pointer value @var{pointer} into the context
+ at var{ctx}.  This is useful to provide command handlers with additional
+application context.
+ at end deftypefun
+
+ at deftypefun void* assuan_get_pointer (@w{assuan_context_t @var{ctx}})
+
+This returns the pointer for context @var{ctx} which has been set using
+the above function.  A common way to use it is by setting the pointer
+before starting the processing loop and to retrieve it right at the
+start of a command handler:
+ at smallexample
+static int
+cmd_foo (assuan_context_t ctx, char *line)
+@{
+  ctrl_t ctrl = assuan_get_pointer (ctx);
+  ...
+@}
+ at end smallexample
+ at end deftypefun
+
+
+ at deftypefun void assuan_set_flag (@w{assuan_context_t @var{ctx}}, @w{assuan_flag_t @var{flag}}, @w{int @var{value}})
+
+Set the the @var{flag} for context @var{ctx} to @var{value}.  Values for
+flags are usually 1 or 0 but certain flags might need other values.
+
+ at deftp {Data type} assuan_flag_t
+The flags are all named and collected in an @code{enum} for better readability.
+Currently only one flag is defined:
+
+ at table @code
+ at item ASSUAN_NO_WAITPID 
+When using a pipe server, by default Libassuan will wait for the forked
+process to die in @code{assuan_disconnect}.  In certain cases this is
+not desirable.  By setting this flag, a call to @code{waitpid} will be
+suppressed and the caller is responsible to cleanup the child process.
+ at item ASSUAN_CONFIDENTIAL
+Uses to return the state of the confidential logging mode.
+ at end table
+ at end deftp
+ at end deftypefun
+
+ at deftypefun int assuan_get_flag (@w{assuan_context_t @var{ctx}}, @w{assuan_flag_t @var{flag}})
+Return the value of @var{flag} in context @var{ctx}. 
+ at end deftypefun 
+
+
+ at deftypefun void assuan_begin_confidential (@w{assuan_context_t @var{ctx}})
+Put the logging feature into confidential mode.  This is to avoid
+logging of sensitive data.
+
+This is identical to:
+ at smallexample
+assuan_set_flag (ctx, ASSUAN_CONFIDENTIAL, 1);
 @end smallexample
 @end deftypefun
 
+
+ at deftypefun void assuan_end_confidential (@w{assuan_context_t @var{ctx}})
+Get the logging feature out of confidential mode.  All data will be
+logged again (if logging is enabled).
+
+This is identical to:
+ at smallexample
+assuan_set_flag (ctx, ASSUAN_CONFIDENTIAL, 0);
+ at end smallexample
+ at end deftypefun
+
+
 @node Reading and Writing
 @section How to communicate with the peer
 
@@ -667,7 +910,31 @@ sending this @code{END} itself.
 This function returns @code{0} on success or an error value.
 @end deftypefun
 
+The input and output of data can be controlled at a higher level using
+an I/O monitor.
 
+ at deftp {Data type} {unsigned int (*assuan_io_monitor_t) (@w{assuan_context_t @var{ctx}}, @w{void *@var{hook_value}}, @w{int @var{inout}}, @w{const char *@var{line}}, @w{size_t @var{linelen}})}
+The monitor function is called right after a line has been received,
+if @var{inout} is @code{ASSUAN_IO_FROM_PEER}, or just before it is
+send, if @var{inout} is @code{ASSUAN_IO_TO_PEER}.  The
+ at var{hook_value} is provided by the user when registering the I/O
+monitor function with a context using @code{assuan_set_io_monitor}.
+The callback function should return the bitwise OR of some (or none) of the
+following flags:
+
+ at table @code
+ at item ASSUAN_IO_MONITOR_NOLOG
+Active logging of this line is suppressed.  This can reduce debug
+output in the case of a frequent message.
+ at item ASSUAN_IO_MONITOR_IGNORE
+The whole output line is discarded.
+ at end table
+ at end deftp
+
+ at deftypefun void assuan_set_io_monitor (@w{assuan_context_t @var{ctx}}, @w{assuan_io_monitor_t @var{io_monitor}}, @w{void *@var{hook_data}})
+This function registers an I/O monitor @var{io_monitor} for the
+context @var{ctx} with the hook value @var{hook_data}.
+ at end deftypefun
 
 
 @c 
@@ -683,18 +950,19 @@ 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:
 
- at deftypefun gpg_error_t assuan_pipe_connect_ext (@w{assuan_context_t *@var{ctx}}, at w{const char *@var{name}}, @w{const char *const @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{int *@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}.
 
-If @var{name} as well as @var{argv} are given as @code{NULL}, only a
-fork but no exec is done.  Thus the child continues to run.  However all
-file descriptors are closed and some special environment variables are
-set. To let the caller detect whether the child or the parent continues,
-the child returns with a @var{ctx} set to @code{NULL}.
+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
+closed and some special environment variables are set.  To let the
+caller detect whether the child or the parent continues, the parent
+returns with @code{"client"} returned in @var{argv} and the child
+returns with @code{"server"} in @var{argv}.
 
 If @var{atfork} is not NULL, this function is called in the child right
 after the fork and the value @var{atforkvalue} is passed as the first
@@ -724,7 +992,7 @@ new console is created and pops up a console window when starting the server
 
 For a pipe-based server you can also use the following legacy function:
 
- at deftypefun gpg_error_t assuan_pipe_connect (@w{assuan_context_t *@var{ctx}}, at w{const char *@var{name}}, @w{const char *const @var{argv}[]}, @w{int *@var{fd_child_list}})
+ at deftypefun gpg_error_t assuan_pipe_connect (@w{assuan_context_t *@var{ctx}}, at w{const char *@var{name}}, @w{const char *@var{argv}[]}, @w{int *@var{fd_child_list}})
 
 A call to @code{assuan_pipe_connect} is equivalent to a call to
 @code{assuan_pipe_connect_ext} with @code{flags} being 0 and without
@@ -1050,19 +1318,6 @@ string @var{line}.  For logging purposes, it is often useful to use
 such a custom hello line which may tell version numbers and such.
 Linefeeds are allowed in this string, however, each line needs to be
 shorter than the Assuan line length limit.
-
- at end deftypefun
-
- at noindent
-As a last initialization step, debugging may be enabled for the
-current connection.  This is done using
-
- at deftypefun void assuan_set_log_stream (@w{assuan_context_t @var{ctx}}, @w{FILE *@var{fp}})
-
-Enable debugging for the context @var{ctx} and write all debugging
-output to the stdio stream @var{fp}.  If the default log stream (used
-for non-context specific events) has not yet been set, a call to this
-functions implicitly sets this stream also to @var{fp}.
 @end deftypefun
 
 @noindent
@@ -1354,32 +1609,6 @@ Some of these functions provide information not available with the
 general functions.
 
 
-
- at deftypefun void assuan_set_pointer (@w{assuan_context_t @var{ctx}}, @w{void *@var{pointer}})
-
-Store the arbitrary pointer value @var{pointer} into the context
- at var{ctx}.  This is useful to provide command handlers with additional
-application context.
- at end deftypefun
-
- at deftypefun void* assuan_get_pointer (@w{assuan_context_t @var{ctx}})
-
-This returns the pointer for context @var{ctx} which has been set using
-the above function.  A common way to use it is by setting the pointer
-before starting the processing loop and to retrieve it right at the
-start of a command handler:
- at smallexample
-static int
-cmd_foo (assuan_context_t ctx, char *line)
-@{
-  ctrl_t ctrl = assuan_get_pointer (ctx);
-  ...
-@}
- at end smallexample
- at end deftypefun
-
-
-
 @deftypefun gpg_error_t assuan_write_status (@w{assuan_context_t @var{ctx}}, @w{const char *@var{keyword}}, @w{const char *@var{text}})
 
 This is a convenience function for a server to send a status line.  You
@@ -1489,34 +1718,6 @@ that error to humans.
 @end deftypefun
 
 
- at deftypefun void assuan_set_flag (@w{assuan_context_t @var{ctx}}, @w{assuan_flag_t @var{flag}}, @w{int @var{value}})
-
-Set the the @var{flag} for context @var{ctx} to @var{value}.  Values for
-flags are usually 1 or 0 but certain flags might need other values.
-
- at deftp {Data type} assuan_flag_t
-The flags are all named and collected in an @code{enum} for better readability.
-Currently only one flag is defined:
-
- at table @code
- at item ASSUAN_NO_WAITPID 
-When using a pipe server, by default Libassuan will wait for the forked
-process to die in @code{assuan_disconnect}.  In certain cases this is
-not desirable.  By setting this flag, a call to @code{waitpid} will be
-suppressed and the caller is responsible to cleanup the child process.
- at item ASSUAN_CONFIDENTIAL
-Uses to return the state of the confidential logging mode.  For changing
-this mode the functions @code{assuan_begin_confidential} and
- at code{assuan_end_confidential} should be used.
- at end table
- at end deftp
-
- at end deftypefun
-
- at deftypefun int assuan_get_flag (@w{assuan_context_t @var{ctx}}, @w{assuan_flag_t @var{flag}})
-Return the value of @var{flag} in context @var{ctx}. 
- at end deftypefun 
-
 
 @deftypefun pid_t assuan_get_pid (@w{assuan_context_t @var{ctx}})
 
@@ -1570,40 +1771,6 @@ thus an entire assuan line may be read without triggering any actual
 I/O.
 @end deftypefun
 
- at deftypefun void assuan_set_io_monitor (@w{assuan_context_t @var{ctx}}, @w{unsigned int} (*@var{monitor})(@w{assuan_context_t @var{ctx}}, @w{int @var{direction}}, @w{const char *@var{line}}, @w{size_t @var{linelen}}))
-
-This function registers an I/O monitor for the context @var{ctx}.  Such
-a monitor function is called right after a line has been received or
-just before it is send.  With @var{direction} set to 1 the monitor has
-been called for an output operation; 0 obviosuly means it has been
-called for an input operation.  If the monitor sets bit 0 in the return
-value, any active logging of the line will be suppressed.  With bit 1
-set, the entire line will be ignored.
- at end deftypefun
-
- at deftypefun void assuan_begin_confidential (@w{assuan_context_t @var{ctx}})
-
-Put the logging feature into confidential mode.  This is to avoid
-logging of sensitive data.
- at end deftypefun
-
- at deftypefun void assuan_end_confidential (@w{assuan_context_t @var{ctx}})
-
-Get the logging feature out of confidential mode.  All data will be
-logged again (if logging is enabled).
- at end deftypefun
-
- at deftypefun FILE* assuan_get_assuan_log_stream (void)
-
-Return the stream which is currently being using for global logging.
- at end deftypefun
-
- at deftypefun @w{const char*} assuan_get_assuan_log_prefix (void)
-
-Return the prefix to be used at the start of a line emitted by assuan
-on the log stream.  The default implementation returns the empty
-string.
- at end deftypefun
 
 
 @c
diff --git a/src/ChangeLog b/src/ChangeLog
index c561abc..627d369 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,88 @@
+2009-09-19  Marcus Brinkmann  <marcus at g10code.de>
+
+	* src/libassuan.vers, src/libassuan.def: Update to new API.
+	* assuan.c, context.c, system.c, debug.c: New files.
+	* Makefile.am (common_sources): Add assuan.c, context.c, system.c
+	and debug.c.
+	* assuan.h: Include <stdarg.h>.  Fix inclusion of <gpg-error.h>.
+	(_ASSUAN_EXT_SYM_PREFIX, _ASSUAN_PREFIX1, _ASSUAN_PREFIX2)
+	(_ASSUAN_PREFIX): Remove support for renaming the whole library,
+	now that we have a stable shared library interface that can evolve
+	to cover all needs (particularly those of GPGME).
+	(assuan_malloc_hooks, assuan_malloc_hooks_t, assuan_log_cb_t)
+	(assuan_io_monitor_t): New types.
+	(ASSUAN_LOG_INIT, ASSUAN_LOG_CTX, ASSUAN_LOG_ENGINE)
+	(ASSUAN_LOG_DATA, ASSUAN_LOG_SYSIO, ASSUAN_IO_FROM_PEER)
+	(ASSUAN_IO_TO_PEER, ASSUAN_IO_MONITOR_NOLOG)
+	(ASSUAN_IO_MONITOR_IGNORE): New symbols.
+	(assuan_set_gpg_err_source, assuan_get_gpg_err_source)
+	(assuan_get_malloc_hooks, assuan_set_log_cb, assuan_get_log_cb)
+	(assuan_new, assuan_new_ext, assuan_release): New function
+	prototypes.
+	(assuan_init_pipe_server, assuan_init_socket_server)
+	(assuan_init_socket_server_ext, assuan_pipe_connect)
+	(assuan_pipe_connect_ext, assuan_socket_connect)
+	(assuan_socket_connect_ext): Take a context argument instead of
+	pointer to context.
+	(assuan_deinit_server, assuan_disconnect)
+	(assuan_set_assuan_err_source): Remove function prototypes.
+	* assuan-defs.h (ASSUAN_GCC_A_PURE): Moved here from XXX
+	(_assuan_error): New macro.
+	(struct assuan_context_s): New members err_source, w32_strerror,
+	malloc_hooks, log_cb, log_cb_data: New members.  Move confidential
+	into flags.  New member engine.
+	(_assuan_log_handler, _assuan_error_default, _assuan_disconnect):
+	New prototypes.
+	(_assuan_new_context): Remove prototype.
+	(_assuan_malloc, _assuan_calloc, _assuan_realloc, _assuan_free):
+	Add context argument to prototype.
+	* assuan-util.c (alloc_func, realloc_func, free_func): Remove
+	global variables.
+	(assuan_set_malloc_hooks, _assuan_malloc, _assuan_realloc)
+	(_assuan_calloc, _assuan_free, assuan_set_pointer)
+	(assuan_get_pointer, assuan_begin_confidential)
+	(assuan_end_confidential, assuan_set_io_monitor, assuan_set_flag)
+	(assuan_get_flag): Move functions to ...
+	* assuan-client.c: Add ctx argument to all invocations of
+	_assuan_error.
+	* assuan-socket-server.c, assuan-socket-connect.c,
+	assuan-connect.c: Likewise.
+	* assuan-buffer.c: Likewise.  Also update access to confidential
+	flag.
+	* assuan-uds.c: Add ctx argument to all invocations of
+	_assuan_malloc, _assuan_realloc, _assuan_calloc, _assuan_free and
+	_assuan_error.
+	* assuan_listen.c, assuan-inquire.c, assuan-handler.c: Likewise.
+	* assuan-error.c (err_source): Remove global variable.
+	(assuan_set_assuan_err_source): Removed function.
+	(_assuan_w32_strerror): Moved here from assuan-logging.c and made
+	thread-safe.
+	(_assuan_error): Removed function (is now macro).
+	* assuan-handler.c: Update access to confidential flag.
+	* assuan-socket-server.c (accept_connection_bottom): Update access
+	to confidential flag in context.
+	(assuan_init_socket_server, assuan_init_socket_server_ext): Take
+	ctx argument instead of pointer to ctx.
+	* assuan-inquire.c (init_membuf, put_membuf, get_membuf)
+	(free_membuf): Take context argument and change all callers.
+	* assuan-socket-server.c (assuan_socket_connect)
+	(assuan_socket_connect_ext): Take ctx argument instead of pointer
+	to ctx.
+	* assuan-pipe-connect.c (initial_handshake, pipe_connect_unix)
+	(socketpair_connect, assuan_pipe_connect)
+	(assuan_pipe_connect_ext): Likewise.
+	(socketpair_connect): Now that ctx is not a pointer argument
+	anymore, return if we are server or client in the argv argument.
+	* assuan-logging.c (_assuan_log_handler): New function.
+	(_assuan_w32_strerror): Move to assuan-error.c
+	* assuan-connect.c (assuan_disconnect): Renamed to ...
+	(_assuan_disconnect): ... this.
+	* assuan-pipe-server.c (_assuan_new_context): Removed function.
+	(assuan_init_pipe_server): Take ctx argument instead of pointer to
+	ctx.
+	(_assuan_release_context): Removed function.
+	(_assuan_deinit_server): Reimplement.
+
 2009-09-01  Marcus Brinkmann  <marcus at g10code.de>
 
 	* assuan.h: Change types in all functions from int to gpg_error_t
@@ -10,7 +95,7 @@
 	(accept_connection, finish_connection): Likewise.
 	(assuan_init_connected_socket_server): Remove.
 	* assuan-defs.h (struct assuan_context_s): Change return type of
-	accept_handler and finish_handler to gpg_error_t.
+	accept_handler and finish_handler to gpg_error_t.  Add io_monitor_data.
 	* assuan-pipe-connect.c (do_finish): Change to void.
 	* assuan-inquire.c (_assuan_inquire_ext_cb): Change type of RC
 	from int to gpg_error_t.
diff --git a/src/Makefile.am b/src/Makefile.am
index 4f6aec3..1e1c46b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -42,7 +42,11 @@ endif
 
 common_sources = \
 	assuan-defs.h \
-	assuan-util.c \
+	assuan.c \
+	context.c \
+	system.c \
+	debug.c \
+	conversion.c \
 	assuan-error.c \
 	assuan-buffer.c \
 	assuan-handler.c \
diff --git a/src/assuan-buffer.c b/src/assuan-buffer.c
index e973341..583d137 100644
--- a/src/assuan-buffer.c
+++ b/src/assuan-buffer.c
@@ -103,7 +103,7 @@ _assuan_read_line (assuan_context_t ctx)
   char *endp = 0;
 
   if (ctx->inbound.eof)
-    return _assuan_error (GPG_ERR_EOF);
+    return _assuan_error (ctx, GPG_ERR_EOF);
 
   atticlen = ctx->inbound.attic.linelen;
   if (atticlen)
@@ -149,7 +149,7 @@ _assuan_read_line (assuan_context_t ctx)
         }
 
       errno = saved_errno;
-      return _assuan_error (gpg_err_code_from_syserror ());
+      return _assuan_error (ctx, gpg_err_code_from_syserror ());
     }
   if (!nread)
     {
@@ -159,7 +159,7 @@ _assuan_read_line (assuan_context_t ctx)
 		 assuan_get_assuan_log_prefix (),
                  (unsigned int)getpid (), (int)ctx->inbound.fd);
 
-      return _assuan_error (GPG_ERR_EOF);
+      return _assuan_error (ctx, GPG_ERR_EOF);
     }
 
   ctx->inbound.attic.pending = 0;
@@ -190,20 +190,20 @@ _assuan_read_line (assuan_context_t ctx)
 
       ctx->inbound.linelen = endp - line;
 
-      monitor_result = (ctx->io_monitor
-                        ? ctx->io_monitor (ctx, 0,
-                                           ctx->inbound.line,
-                                           ctx->inbound.linelen)
-                        : 0);
-      if ( (monitor_result & 2) )
+      monitor_result = 0;
+      if (ctx->io_monitor)
+	monitor_result = ctx->io_monitor (ctx, ctx->io_monitor_data, 0,
+					  ctx->inbound.line,
+					  ctx->inbound.linelen);
+      if (monitor_result & ASSUAN_IO_MONITOR_IGNORE)
         ctx->inbound.linelen = 0;
       
-      if (ctx->log_fp && !(monitor_result & 1))
+      if (ctx->log_fp && !(monitor_result & ASSUAN_IO_MONITOR_NOLOG))
 	{
 	  fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- ",
 		   assuan_get_assuan_log_prefix (),
                    (unsigned int)getpid (), (int)ctx->inbound.fd);
-	  if (ctx->confidential)
+	  if (ctx->flags.confidential)
 	    fputs ("[Confidential data not shown]", ctx->log_fp);
 	  else
 	    _assuan_log_print_buffer (ctx->log_fp,
@@ -221,9 +221,9 @@ _assuan_read_line (assuan_context_t ctx)
                  (unsigned int)getpid (), (int)ctx->inbound.fd);
       *line = 0;
       ctx->inbound.linelen = 0;
-      return _assuan_error (ctx->inbound.eof 
-			? GPG_ERR_ASS_INCOMPLETE_LINE
-			: GPG_ERR_ASS_LINE_TOO_LONG);
+      return _assuan_error (ctx, ctx->inbound.eof 
+			    ? GPG_ERR_ASS_INCOMPLETE_LINE
+			    : GPG_ERR_ASS_LINE_TOO_LONG);
     }
 }
 
@@ -243,7 +243,7 @@ assuan_read_line (assuan_context_t ctx, char **line, size_t *linelen)
   gpg_error_t err;
 
   if (!ctx)
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
 
   do
     {
@@ -288,17 +288,17 @@ _assuan_write_line (assuan_context_t ctx, const char *prefix,
         len = ASSUAN_LINELENGTH - prefixlen - 2 - 1;
     }
 
-  monitor_result = (ctx->io_monitor
-                    ? ctx->io_monitor (ctx, 1, line, len)
-                    : 0);
+  monitor_result = 0;
+  if (ctx->io_monitor)
+    monitor_result = ctx->io_monitor (ctx, ctx->io_monitor_data, 1, line, len);
 
   /* Fixme: we should do some kind of line buffering.  */
-  if (ctx->log_fp && !(monitor_result & 1))
+  if (ctx->log_fp && !(monitor_result & ASSUAN_IO_MONITOR_NOLOG))
     {
       fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ",
 	       assuan_get_assuan_log_prefix (),
                (unsigned int)getpid (), (int)ctx->inbound.fd);
-      if (ctx->confidential)
+      if (ctx->flags.confidential)
 	fputs ("[Confidential data not shown]", ctx->log_fp);
       else
         {
@@ -309,22 +309,22 @@ _assuan_write_line (assuan_context_t ctx, const char *prefix,
       putc ('\n', ctx->log_fp);
     }
 
-  if (prefixlen && !(monitor_result & 2))
+  if (prefixlen && !(monitor_result & ASSUAN_IO_MONITOR_IGNORE))
     {
       rc = writen (ctx, prefix, prefixlen);
       if (rc)
-	rc = _assuan_error (gpg_err_code_from_syserror ());
+	rc = _assuan_error (ctx, gpg_err_code_from_syserror ());
     }
-  if (!rc && !(monitor_result & 2))
+  if (!rc && !(monitor_result & ASSUAN_IO_MONITOR_IGNORE))
     {
       rc = writen (ctx, line, len);
       if (rc)
-	rc = _assuan_error (gpg_err_code_from_syserror ());
+	rc = _assuan_error (ctx, gpg_err_code_from_syserror ());
       if (!rc)
         {
           rc = writen (ctx, "\n", 1);
           if (rc)
-	    rc = _assuan_error (gpg_err_code_from_syserror ());
+	    rc = _assuan_error (ctx, gpg_err_code_from_syserror ());
         }
     }
   return rc;
@@ -338,7 +338,7 @@ assuan_write_line (assuan_context_t ctx, const char *line)
   const char *str;
 
   if (! ctx)
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
 
   /* Make sure that we never take a LF from the user - this might
      violate the protocol. */
@@ -403,20 +403,20 @@ _assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size)
         }
       
       
-      monitor_result = (ctx->io_monitor
-                        ? ctx->io_monitor (ctx, 1,
-                                           ctx->outbound.data.line, linelen)
-                        : 0);
+      monitor_result = 0;
+      if (ctx->io_monitor)
+	monitor_result = ctx->io_monitor (ctx, ctx->io_monitor_data, 1,
+					  ctx->outbound.data.line, linelen);
 
       if (linelen >= LINELENGTH-2-2)
         {
-          if (ctx->log_fp && !(monitor_result & 1))
+          if (ctx->log_fp && !(monitor_result & ASSUAN_IO_MONITOR_NOLOG))
             {
 	      fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ",
 		       assuan_get_assuan_log_prefix (),
                        (unsigned int)getpid (), (int)ctx->inbound.fd);
 
-              if (ctx->confidential)
+              if (ctx->flags.confidential)
                 fputs ("[Confidential data not shown]", ctx->log_fp);
               else 
                 _assuan_log_print_buffer (ctx->log_fp, 
@@ -426,7 +426,7 @@ _assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size)
             }
           *line++ = '\n';
           linelen++;
-          if ( !(monitor_result & 2)
+          if ( !(monitor_result & ASSUAN_IO_MONITOR_IGNORE)
                && writen (ctx, ctx->outbound.data.line, linelen))
             {
               ctx->outbound.data.error = gpg_err_code_from_syserror ();
@@ -459,19 +459,19 @@ _assuan_cookie_write_flush (void *cookie)
   linelen = ctx->outbound.data.linelen;
   line += linelen;
 
-  monitor_result = (ctx->io_monitor
-                    ? ctx->io_monitor (ctx, 1,
-                                       ctx->outbound.data.line, linelen)
-                    : 0);
+  monitor_result = 0;
+  if (ctx->io_monitor)
+    monitor_result = ctx->io_monitor (ctx, ctx->io_monitor_data, 1,
+				      ctx->outbound.data.line, linelen);
   
   if (linelen)
     {
-      if (ctx->log_fp && !(monitor_result & 1))
+      if (ctx->log_fp && !(monitor_result & ASSUAN_IO_MONITOR_NOLOG))
 	{
 	  fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ",
 		   assuan_get_assuan_log_prefix (),
                    (unsigned int)getpid (), (int)ctx->inbound.fd);
-	  if (ctx->confidential)
+	  if (ctx->flags.confidential)
 	    fputs ("[Confidential data not shown]", ctx->log_fp);
 	  else
 	    _assuan_log_print_buffer (ctx->log_fp,
@@ -480,7 +480,7 @@ _assuan_cookie_write_flush (void *cookie)
 	}
       *line++ = '\n';
       linelen++;
-      if (! (monitor_result & 2)
+      if (! (monitor_result & ASSUAN_IO_MONITOR_IGNORE)
            && writen (ctx, ctx->outbound.data.line, linelen))
         {
           ctx->outbound.data.error = gpg_err_code_from_syserror ();
@@ -517,9 +517,9 @@ gpg_error_t
 assuan_send_data (assuan_context_t ctx, const void *buffer, size_t length)
 {
   if (!ctx)
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
   if (!buffer && length > 1)
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
 
   if (!buffer)
     { /* flush what we have */
@@ -548,7 +548,7 @@ assuan_sendfd (assuan_context_t ctx, assuan_fd_t fd)
 #ifdef USE_DESCRIPTOR_PASSING
     return 0;
 #else
-    return _assuan_error (GPG_ERR_NOT_IMPLEMENTED);
+  return _assuan_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
 #endif
 
   if (! ctx->io->sendfd)
diff --git a/src/assuan-client.c b/src/assuan-client.c
index 3d3748c..aa74f81 100644
--- a/src/assuan-client.c
+++ b/src/assuan-client.c
@@ -109,7 +109,7 @@ _assuan_read_from_server (assuan_context_t ctx, int *okay, int *off)
       *off = 3;
     }
   else
-    rc = _assuan_error (GPG_ERR_ASS_INV_RESPONSE);
+    rc = _assuan_error (ctx, GPG_ERR_ASS_INV_RESPONSE);
   return rc;
 }
 
@@ -169,7 +169,7 @@ assuan_transact (assuan_context_t ctx,
   else if (okay == 2)
     {
       if (!data_cb)
-        rc = _assuan_error (GPG_ERR_ASS_NO_DATA_CB);
+        rc = _assuan_error (ctx, GPG_ERR_ASS_NO_DATA_CB);
       else 
         {
           char *s, *d;
@@ -198,7 +198,7 @@ assuan_transact (assuan_context_t ctx,
         {
           assuan_write_line (ctx, "END"); /* get out of inquire mode */
           _assuan_read_from_server (ctx, &okay, &off); /* dummy read */
-          rc = _assuan_error (GPG_ERR_ASS_NO_INQUIRE_CB);
+          rc = _assuan_error (ctx, GPG_ERR_ASS_NO_INQUIRE_CB);
         }
       else
         {
@@ -219,7 +219,7 @@ assuan_transact (assuan_context_t ctx,
   else if (okay == 5)
     {
       if (!data_cb)
-        rc = _assuan_error (GPG_ERR_ASS_NO_DATA_CB);
+        rc = _assuan_error (ctx, GPG_ERR_ASS_NO_DATA_CB);
       else 
         {
           rc = data_cb (data_cb_arg, NULL, 0);
diff --git a/src/assuan-connect.c b/src/assuan-connect.c
index c2c7f42..f5540a1 100644
--- a/src/assuan-connect.c
+++ b/src/assuan-connect.c
@@ -36,18 +36,24 @@
 
 /* Disconnect and release the context CTX. */
 void
-assuan_disconnect (assuan_context_t ctx)
+_assuan_disconnect (assuan_context_t ctx)
 {
-  if (ctx)
-    {
-      assuan_write_line (ctx, "BYE");
-      ctx->finish_handler (ctx);
-      ctx->deinit_handler (ctx);
-      ctx->deinit_handler = NULL;
-      _assuan_release_context (ctx);
-    }
+  assuan_write_line (ctx, "BYE");
+  ctx->finish_handler (ctx);
+  ctx->finish_handler = NULL;
+  ctx->deinit_handler (ctx);
+  ctx->deinit_handler = NULL;
+
+  _assuan_inquire_release (ctx);
+  _assuan_free (ctx, ctx->hello_line);
+  ctx->hello_line = NULL;
+  _assuan_free (ctx, ctx->okay_line);
+  ctx->okay_line = NULL;
+  _assuan_free (ctx, ctx->cmdtbl);
+  ctx->cmdtbl = NULL;
 }
 
+
 /* Return the PID of the peer or -1 if not known. This function works
    in some situations where assuan_get_ucred fails. */
 pid_t
@@ -65,9 +71,9 @@ gpg_error_t
 assuan_get_peercred (assuan_context_t ctx, pid_t *pid, uid_t *uid, gid_t *gid)
 {
   if (!ctx)
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
   if (!ctx->peercred.valid)
-    return _assuan_error (GPG_ERR_ASS_GENERAL);
+    return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);
 
 #ifdef HAVE_SO_PEERCRED
   if (pid)
diff --git a/src/assuan-defs.h b/src/assuan-defs.h
index 5fc14f4..1d6acee 100644
--- a/src/assuan-defs.h
+++ b/src/assuan-defs.h
@@ -31,6 +31,12 @@
 
 #include "assuan.h"
 
+#if __GNUC__ > 2 
+# define ASSUAN_GCC_A_PURE  __attribute__ ((__pure__))
+#else
+# define ASSUAN_GCC_A_PURE
+#endif
+
 #ifndef HAVE_W32_SYSTEM
 #define DIRSEP_C '/'
 #else
@@ -39,6 +45,9 @@
 
 #define LINELENGTH ASSUAN_LINELENGTH
 
+/* Generate an error code specific to a context.  */
+#define _assuan_error(ctx, errcode) gpg_err_make ((ctx)->err_source, errcode)
+
 
 struct cmdtbl_s
 {
@@ -60,40 +69,71 @@ struct assuan_io
   gpg_error_t (*receivefd) (assuan_context_t, assuan_fd_t *);
 };
 
-
-/* The global variable with the optional hook fucntions.  */
-extern struct assuan_io_hooks _assuan_io_hooks;
-
-
+

 /* The context we use with most functions. */
 struct assuan_context_s
 {
-  gpg_error_t err_no;
-  const char *err_str;
+  /* Members managed by the generic routines in assuan.c.  */
+
+  /* The error source for errors generated from this context.  */
+  gpg_err_source_t err_source;
+
+#ifdef HAVE_W32_SYSTEM
+  /* The per-context w32 error string.  */
+  char w32_strerror[256];
+#endif
+
+  /* The allocation hooks.  */
+  struct assuan_malloc_hooks malloc_hooks;
+
+  /* Logging callback handler.  */
+  assuan_log_cb_t log_cb;
+  void *log_cb_data;
+
+  void *user_pointer;
 
   /* Context specific flags (cf. assuan_flag_t). */
   struct
   {
-    unsigned int no_waitpid : 1; /* See ASSUAN_NO_WAITPID. */
+    unsigned int no_waitpid : 1;
+    unsigned int confidential : 1;
   } flags;
 
-  int confidential;
+  /* If set, this is called right before logging an I/O line.  */
+  assuan_io_monitor_t io_monitor;
+  void *io_monitor_data;
+
+  /* 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);
+  } engine;
+
+
+  /* Engine specific or other subsystem members.  */
+
+  /* assuan-logging.c.  Does not require deallocation from us.  */
+  FILE *log_fp;
+
+  /* assuan-util.c  */
+  gpg_error_t err_no;
+  const char *err_str;
+
   int is_server;      /* Set if this is context belongs to a server */
   int in_inquire;
   int in_process_next;
   int in_command;
 
   /* The following members are used by assuan_inquire_ext.  */
-  int (*inquire_cb) (void *cb_data, int rc, unsigned char *buf, size_t len);
+  gpg_error_t (*inquire_cb) (void *cb_data, gpg_error_t rc,
+			     unsigned char *buf, size_t len);
   void *inquire_cb_data;
   void *inquire_membuf;
 
   char *hello_line;
   char *okay_line;    /* See assuan_set_okay_line() */
 
-  void *user_pointer;  /* For assuan_get_pointer and assuan_set_pointer (). */
-
-  FILE *log_fp;
 
   struct {
     assuan_fd_t fd;
@@ -155,7 +195,7 @@ struct assuan_context_s
 
   void (*deinit_handler)(assuan_context_t);
   gpg_error_t (*accept_handler)(assuan_context_t);
-  gpg_error_t (*finish_handler)(assuan_context_t);
+  void (*finish_handler)(assuan_context_t);
 
   struct cmdtbl_s *cmdtbl;
   size_t cmdtbl_used; /* used entries */
@@ -170,27 +210,35 @@ struct assuan_context_s
 
   /* This function is called right after a command has been processed.
      It may be used to command related cleanup.  */
-  void (*post_cmd_notify_fnc)(assuan_context_t, int);
-
-  /* If set, this is called right before logging an I/O line.  With
-     DIRECTION set to 1 it is called for an output oeration; 0 means
-     an input operation. If bit 0 is set in the return value, the
-     logging of the line will be suppressed.  With bit 1 set, the
-     entire line will be ignored. */
-  unsigned int (*io_monitor)(assuan_context_t ctx,
-                             int direction,
-                             const char *line,
-                             size_t linelen);
+  void (*post_cmd_notify_fnc)(assuan_context_t, gpg_error_t);
+
 
   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;
+
+
 };
 
+

+/* Release all resources associated with an engine operation.  */
+void _assuan_reset (assuan_context_t ctx);
+
+/* Default log handler.  */
+int _assuan_log_handler (assuan_context_t ctx, void *hook,
+			  unsigned int cat, const char *msg);
+
+

+/* Manage memory specific to a context.  */
+void *_assuan_malloc (assuan_context_t ctx, size_t cnt);
+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);
+
+

 /*-- assuan-pipe-server.c --*/
-gpg_error_t _assuan_new_context (assuan_context_t *r_ctx);
 void _assuan_release_context (assuan_context_t ctx);
 
 /*-- assuan-uds.c --*/
@@ -223,16 +271,9 @@ void _assuan_inquire_release (assuan_context_t ctx);
 int _assuan_error_is_eagain (gpg_error_t err);
 
 
-/*-- assuan-util.c --*/
-void *_assuan_malloc (size_t n);
-void *_assuan_calloc (size_t n, size_t m);
-void *_assuan_realloc (void *p, size_t n);
-void  _assuan_free (void *p);
-
-gpg_error_t _assuan_error (gpg_err_code_t errcode);
 
 #define set_error(c,e,t)						\
-       assuan_set_error ((c), _assuan_error (e), (t))
+  assuan_set_error ((c), _assuan_error (c,e), (t))
 
 #ifdef HAVE_W32_SYSTEM
 const char *_assuan_w32_strerror (int ec);
@@ -241,15 +282,7 @@ const char *_assuan_w32_strerror (int ec);
 
 
 /*-- assuan-logging.c --*/
-void _assuan_set_default_log_stream (FILE *fp);
-
-void _assuan_log_printf (const char *format, ...)
-#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
- __attribute__ ((format (printf,1,2)))
-#endif
-     ;
-void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t  length);
-void _assuan_log_sanitized_string (const char *string);
+void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length);
 
 
 /*-- assuan-io.c --*/
@@ -322,4 +355,10 @@ int putc_unlocked (int c, FILE *stream);
 #endif
 
 
+void _assuan_disconnect (assuan_context_t ctx);
+
+/* Encode the C formatted string SRC and return the malloc'ed result.  */
+char *_assuan_encode_c_string (assuan_context_t ctx, const char *src);
+
+
 #endif /*ASSUAN_DEFS_H*/
diff --git a/src/assuan-error.c b/src/assuan-error.c
index 4eba7ff..60cb0d3 100644
--- a/src/assuan-error.c
+++ b/src/assuan-error.c
@@ -29,30 +29,6 @@
 #include "assuan.h"
 #include "assuan-defs.h"
 
-/* If true the modern gpg-error style error codes are used in the
-   API. */
-static gpg_err_source_t err_source;
-
-/* Enable gpg-error style error codes.  ERRSOURCE is one of gpg-error
-   sources.  Note, that this function is not thread-safe and should be
-   used right at startup. Switching back to the old style mode is not
-   supported. */
-void
-assuan_set_assuan_err_source (gpg_err_source_t errsource)
-{
-  errsource &= 0xff;
-  err_source = errsource ? errsource : 31 /*GPG_ERR_SOURCE_ANY*/;
-}
-
-
-/* Helper to map old style Assuan error codes to gpg-error codes.
-   This is used internally to keep an compatible ABI. */
-gpg_error_t
-_assuan_error (gpg_err_code_t errcode)
-{
-  return gpg_err_make (err_source, errcode);
-}
-
 
 /* A small helper function to treat EAGAIN transparently to the
    caller.  */
@@ -68,3 +44,20 @@ _assuan_error_is_eagain (gpg_error_t err)
   else
     return 0;
 }
+
+

+
+#ifdef HAVE_W32_SYSTEM
+char *
+_assuan_w32_strerror (assuan_context_t ctx, int ec)
+{
+  if (ec == -1)
+    ec = (int)GetLastError ();
+  FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec,
+                 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+                 ctx->w32_strerror, sizeof (ctx->w32_strerror) - 1, NULL);
+
+  return ctx->w32_strerror;
+}
+#endif
+
diff --git a/src/assuan-handler.c b/src/assuan-handler.c
index 057d7e7..da5d4bf 100644
--- a/src/assuan-handler.c
+++ b/src/assuan-handler.c
@@ -27,7 +27,7 @@
 #include <errno.h>
 
 #include "assuan-defs.h"
-
+#include "debug.h"
 
 
 #define spacep(p)  (*(p) == ' ' || *(p) == '\t')
@@ -123,7 +123,7 @@ std_handler_bye (assuan_context_t ctx, char *line)
   assuan_close_input_fd (ctx);
   assuan_close_output_fd (ctx);
   /* pretty simple :-) */
-  return PROCESS_DONE (ctx, _assuan_error (GPG_ERR_EOF));
+  return PROCESS_DONE (ctx, _assuan_error (ctx, GPG_ERR_EOF));
 }
   
 static gpg_error_t
@@ -287,7 +287,7 @@ assuan_register_command (assuan_context_t ctx,
     cmd_name = NULL;
 
   if (!cmd_name)
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
 
   if (!handler)
     { /* find a default handler. */
@@ -308,18 +308,18 @@ assuan_register_command (assuan_context_t ctx,
   if (!ctx->cmdtbl)
     {
       ctx->cmdtbl_size = 50;
-      ctx->cmdtbl = _assuan_calloc (ctx->cmdtbl_size, sizeof *ctx->cmdtbl);
+      ctx->cmdtbl = _assuan_calloc (ctx, ctx->cmdtbl_size, sizeof *ctx->cmdtbl);
       if (!ctx->cmdtbl)
-	return _assuan_error (gpg_err_code_from_syserror ());
+	return _assuan_error (ctx, gpg_err_code_from_syserror ());
       ctx->cmdtbl_used = 0;
     }
   else if (ctx->cmdtbl_used >= ctx->cmdtbl_size)
     {
       struct cmdtbl_s *x;
 
-      x = _assuan_realloc ( ctx->cmdtbl, (ctx->cmdtbl_size+10) * sizeof *x);
+      x = _assuan_realloc (ctx, ctx->cmdtbl, (ctx->cmdtbl_size+10) * sizeof *x);
       if (!x)
-	return _assuan_error (gpg_err_code_from_syserror ());
+	return _assuan_error (ctx, gpg_err_code_from_syserror ());
       ctx->cmdtbl = x;
       ctx->cmdtbl_size += 50;
     }
@@ -335,7 +335,7 @@ assuan_register_post_cmd_notify (assuan_context_t ctx,
                                  void (*fnc)(assuan_context_t, gpg_error_t))
 {
   if (!ctx)
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
   ctx->post_cmd_notify_fnc = fnc;
   return 0;
 }
@@ -345,7 +345,7 @@ assuan_register_bye_notify (assuan_context_t ctx,
                             void (*fnc)(assuan_context_t))
 {
   if (!ctx)
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
   ctx->bye_notify_fnc = fnc;
   return 0;
 }
@@ -355,7 +355,7 @@ assuan_register_reset_notify (assuan_context_t ctx,
                               void (*fnc)(assuan_context_t))
 {
   if (!ctx)
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
   ctx->reset_notify_fnc = fnc;
   return 0;
 }
@@ -365,7 +365,7 @@ assuan_register_cancel_notify (assuan_context_t ctx,
                                void (*fnc)(assuan_context_t))
 {
   if (!ctx)
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
   ctx->cancel_notify_fnc = fnc;
   return 0;
 }
@@ -376,7 +376,7 @@ assuan_register_option_handler (assuan_context_t ctx,
 						   const char*, const char*))
 {
   if (!ctx)
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
   ctx->option_handler_fnc = fnc;
   return 0;
 }
@@ -386,7 +386,7 @@ assuan_register_input_notify (assuan_context_t ctx,
                               void (*fnc)(assuan_context_t, const char *))
 {
   if (!ctx)
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
   ctx->input_notify_fnc = fnc;
   return 0;
 }
@@ -396,7 +396,7 @@ assuan_register_output_notify (assuan_context_t ctx,
                               void (*fnc)(assuan_context_t, const char *))
 {
   if (!ctx)
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
   ctx->output_notify_fnc = fnc;
   return 0;
 }
@@ -508,7 +508,7 @@ gpg_error_t
 assuan_process_done (assuan_context_t ctx, gpg_error_t rc)
 {
   if (!ctx->in_command)
-    return _assuan_error (GPG_ERR_ASS_GENERAL);
+    return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);
 
   ctx->in_command = 0;
 
@@ -557,10 +557,10 @@ assuan_process_done (assuan_context_t ctx, gpg_error_t rc)
   if (ctx->post_cmd_notify_fnc)
     ctx->post_cmd_notify_fnc (ctx, rc);
   
-  ctx->confidential = 0;
+  ctx->flags.confidential = 0;
   if (ctx->okay_line)
     {
-      _assuan_free (ctx->okay_line);
+      _assuan_free (ctx, ctx->okay_line);
       ctx->okay_line = NULL;
     }
 
@@ -613,7 +613,8 @@ process_next (assuan_context_t ctx)
       /* Should not happen.  The client is sending data while we are
 	 in a command and not waiting for an inquire.  We log an error
 	 and discard it.  */
-      _assuan_log_printf ("unexpected client data\n");
+      TRACE0 (ctx, ASSUAN_LOG_DATA, "process_next", ctx,
+	      "unexpected client data");
       rc = 0;
     }
 
@@ -649,7 +650,7 @@ process_request (assuan_context_t ctx)
   gpg_error_t rc;
 
   if (ctx->in_inquire)
-    return _assuan_error (GPG_ERR_ASS_NESTED_COMMANDS);
+    return _assuan_error (ctx, GPG_ERR_ASS_NESTED_COMMANDS);
 
   do
     {
@@ -798,22 +799,22 @@ gpg_error_t
 assuan_set_okay_line (assuan_context_t ctx, const char *line)
 {
   if (!ctx)
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
   if (!line)
     {
-      _assuan_free (ctx->okay_line);
+      _assuan_free (ctx, ctx->okay_line);
       ctx->okay_line = NULL;
     }
   else
     {
       /* FIXME: we need to use gcry_is_secure() to test whether
          we should allocate the entire line in secure memory */
-      char *buf = _assuan_malloc (3 + strlen(line) + 1);
+      char *buf = _assuan_malloc (ctx, 3 + strlen(line) + 1);
       if (!buf)
-        return _assuan_error (gpg_err_code_from_syserror ());
+        return _assuan_error (ctx, gpg_err_code_from_syserror ());
       strcpy (buf, "OK ");
       strcpy (buf+3, line);
-      _assuan_free (ctx->okay_line);
+      _assuan_free (ctx, ctx->okay_line);
       ctx->okay_line = buf;
     }
   return 0;
@@ -831,7 +832,7 @@ assuan_write_status (assuan_context_t ctx,
   gpg_error_t ae;
 
   if ( !ctx || !keyword)
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
   if (!text)
     text = "";
 
@@ -847,7 +848,7 @@ assuan_write_status (assuan_context_t ctx,
         }
       ae = assuan_write_line (ctx, buffer);
     }
-  else if ( (helpbuf = _assuan_malloc (n)) )
+  else if ( (helpbuf = _assuan_malloc (ctx, n)) )
     {
       strcpy (helpbuf, "S ");
       strcat (helpbuf, keyword);
@@ -857,7 +858,7 @@ assuan_write_status (assuan_context_t ctx,
           strcat (helpbuf, text);
         }
       ae = assuan_write_line (ctx, helpbuf);
-      _assuan_free (helpbuf);
+      _assuan_free (ctx, helpbuf);
     }
   else
     ae = 0;
diff --git a/src/assuan-inquire.c b/src/assuan-inquire.c
index 55ab280..dba7cb1 100644
--- a/src/assuan-inquire.c
+++ b/src/assuan-inquire.c
@@ -52,7 +52,8 @@ struct membuf
    the code with out of core checks.  */
 
 static void
-init_membuf (struct membuf *mb, int initiallen, size_t maxlen)
+init_membuf (assuan_context_t ctx,
+	     struct membuf *mb, int initiallen, size_t maxlen)
 {
   mb->len = 0;
   mb->size = initiallen;
@@ -60,13 +61,14 @@ init_membuf (struct membuf *mb, int initiallen, size_t maxlen)
   mb->too_large = 0;
   mb->maxlen = maxlen;
   /* we need to allocate one byte more for get_membuf */
-  mb->buf = _assuan_malloc (initiallen+1);
+  mb->buf = _assuan_malloc (ctx, initiallen + 1);
   if (!mb->buf)
       mb->out_of_core = 1;
 }
 
 static void
-put_membuf (struct membuf *mb, const void *buf, size_t len)
+put_membuf (assuan_context_t ctx,
+	    struct membuf *mb, const void *buf, size_t len)
 {
   if (mb->out_of_core || mb->too_large)
     return;
@@ -83,7 +85,7 @@ put_membuf (struct membuf *mb, const void *buf, size_t len)
       
       mb->size += len + 1024;
       /* we need to allocate one byte more for get_membuf */
-      p = _assuan_realloc (mb->buf, mb->size+1);
+      p = _assuan_realloc (ctx, mb->buf, mb->size + 1);
       if (!p)
         {
           mb->out_of_core = 1;
@@ -96,13 +98,13 @@ put_membuf (struct membuf *mb, const void *buf, size_t len)
 }
 
 static void *
-get_membuf (struct membuf *mb, size_t *len)
+get_membuf (assuan_context_t ctx, struct membuf *mb, size_t *len)
 {
   char *p;
 
   if (mb->out_of_core || mb->too_large)
     {
-      _assuan_free (mb->buf);
+      _assuan_free (ctx, mb->buf);
       mb->buf = NULL;
       return NULL;
     }
@@ -116,9 +118,9 @@ get_membuf (struct membuf *mb, size_t *len)
 }
 
 static void
-free_membuf (struct membuf *mb)
+free_membuf (assuan_context_t ctx, struct membuf *mb)
 {
-  _assuan_free (mb->buf);
+  _assuan_free (ctx, mb->buf);
   mb->buf = NULL;
 }
 
@@ -148,20 +150,20 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,
   int nodataexpected;
 
   if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf)))
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
   nodataexpected = !r_buffer && !r_length && !maxlen;
   if (!nodataexpected && (!r_buffer || !r_length))
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
   if (!ctx->is_server)
-    return _assuan_error (GPG_ERR_ASS_NOT_A_SERVER);
+    return _assuan_error (ctx, GPG_ERR_ASS_NOT_A_SERVER);
   if (ctx->in_inquire)
-    return _assuan_error (GPG_ERR_ASS_NESTED_COMMANDS);
+    return _assuan_error (ctx, GPG_ERR_ASS_NESTED_COMMANDS);
   
   ctx->in_inquire = 1;
   if (nodataexpected)
     memset (&mb, 0, sizeof mb); /* avoid compiler warnings */
   else
-    init_membuf (&mb, maxlen? maxlen:1024, maxlen);
+    init_membuf (ctx, &mb, maxlen? maxlen:1024, maxlen);
 
   strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword);
   rc = assuan_write_line (ctx, cmdbuf);
@@ -186,12 +188,12 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,
         break; /* END command received*/
       if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N')
         {
-          rc = _assuan_error (GPG_ERR_ASS_CANCELED);
+          rc = _assuan_error (ctx, GPG_ERR_ASS_CANCELED);
           goto leave;
         }
       if (line[0] != 'D' || line[1] != ' ' || nodataexpected)
         {
-          rc = _assuan_error (GPG_ERR_ASS_UNEXPECTED_CMD);
+          rc = _assuan_error (ctx, GPG_ERR_ASS_UNEXPECTED_CMD);
           goto leave;
         }
       if (linelen < 3)
@@ -204,7 +206,7 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,
         {
           for (;linelen && *p != '%'; linelen--, p++)
             ;
-          put_membuf (&mb, line, p-line);
+          put_membuf (ctx, &mb, line, p-line);
           if (linelen > 2)
             { /* handle escaping */
               unsigned char tmp[1];
@@ -212,27 +214,27 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,
               *tmp = xtoi_2 (p);
               p += 2;
               linelen -= 3;
-              put_membuf (&mb, tmp, 1);
+              put_membuf (ctx, &mb, tmp, 1);
             }
           line = p;
         }
       if (mb.too_large)
         {
-          rc = _assuan_error (GPG_ERR_ASS_TOO_MUCH_DATA);
+          rc = _assuan_error (ctx, GPG_ERR_ASS_TOO_MUCH_DATA);
           goto leave;
         }
     }
 
   if (!nodataexpected)
     {
-      *r_buffer = get_membuf (&mb, r_length);
+      *r_buffer = get_membuf (ctx, &mb, r_length);
       if (!*r_buffer)
-	rc = _assuan_error (gpg_err_code_from_syserror ());
+	rc = _assuan_error (ctx, gpg_err_code_from_syserror ());
     }
 
  leave:
   if (!nodataexpected)
-    free_membuf (&mb);
+    free_membuf (ctx, &mb);
   ctx->in_inquire = 0;
   return rc;
 }
@@ -245,7 +247,7 @@ _assuan_inquire_release (assuan_context_t ctx)
     {
       if (ctx->inquire_membuf)
 	{
-	  free_membuf (ctx->inquire_membuf);
+	  free_membuf (ctx, ctx->inquire_membuf);
 	  free (ctx->inquire_membuf);
 	}
       ctx->in_inquire = 0;
@@ -268,7 +270,7 @@ _assuan_inquire_ext_cb (assuan_context_t ctx)
 
   if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N')
     {
-      rc = _assuan_error (GPG_ERR_ASS_CANCELED);
+      rc = _assuan_error (ctx, GPG_ERR_ASS_CANCELED);
       goto leave;
     }
   if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
@@ -280,7 +282,7 @@ _assuan_inquire_ext_cb (assuan_context_t ctx)
 
   if (line[0] != 'D' || line[1] != ' ' || mb == NULL)
     {
-      rc = _assuan_error (GPG_ERR_ASS_UNEXPECTED_CMD);
+      rc = _assuan_error (ctx, GPG_ERR_ASS_UNEXPECTED_CMD);
       goto leave;
     }
   
@@ -294,7 +296,7 @@ _assuan_inquire_ext_cb (assuan_context_t ctx)
     {
       for (;linelen && *p != '%'; linelen--, p++)
 	;
-      put_membuf (mb, line, p-line);
+      put_membuf (ctx, mb, line, p-line);
       if (linelen > 2)
 	{ /* handle escaping */
 	  unsigned char tmp[1];
@@ -302,13 +304,13 @@ _assuan_inquire_ext_cb (assuan_context_t ctx)
 	  *tmp = xtoi_2 (p);
 	  p += 2;
 	  linelen -= 3;
-	  put_membuf (mb, tmp, 1);
+	  put_membuf (ctx, mb, tmp, 1);
 	}
       line = p;
     }
   if (mb->too_large)
     {
-      rc = _assuan_error (GPG_ERR_ASS_TOO_MUCH_DATA);
+      rc = _assuan_error (ctx, GPG_ERR_ASS_TOO_MUCH_DATA);
       goto leave;
     }
 
@@ -321,10 +323,10 @@ _assuan_inquire_ext_cb (assuan_context_t ctx)
     
     if (mb)
       {
-	buf = get_membuf (mb, &buf_len);
+	buf = get_membuf (ctx, mb, &buf_len);
 	if (!buf)
-	  rc = _assuan_error (gpg_err_code_from_syserror ());
-	free_membuf (mb);
+	  rc = _assuan_error (ctx, gpg_err_code_from_syserror ());
+	free_membuf (ctx, mb);
 	free (mb);
 	ctx->inquire_membuf = NULL;
       }
@@ -359,22 +361,22 @@ assuan_inquire_ext (assuan_context_t ctx, const char *keyword, size_t maxlen,
   char cmdbuf[LINELENGTH-10]; /* (10 = strlen ("INQUIRE ")+CR,LF) */
 
   if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf)))
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
   if (!ctx->is_server)
-    return _assuan_error (GPG_ERR_ASS_NOT_A_SERVER);
+    return _assuan_error (ctx, GPG_ERR_ASS_NOT_A_SERVER);
   if (ctx->in_inquire)
-    return _assuan_error (GPG_ERR_ASS_NESTED_COMMANDS);
+    return _assuan_error (ctx, GPG_ERR_ASS_NESTED_COMMANDS);
 
   mb = malloc (sizeof (struct membuf));
   if (!mb)
-    return _assuan_error (gpg_err_code_from_syserror ());
-  init_membuf (mb, maxlen ? maxlen : 1024, maxlen);
+    return _assuan_error (ctx, gpg_err_code_from_syserror ());
+  init_membuf (ctx, mb, maxlen ? maxlen : 1024, maxlen);
 
   strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword);
   rc = assuan_write_line (ctx, cmdbuf);
   if (rc)
     {
-      free_membuf (mb); 
+      free_membuf (ctx, mb); 
       free (mb);
       return rc;
     }
diff --git a/src/assuan-io-pth.c b/src/assuan-io-pth.c
index e24d435..7e438e9 100644
--- a/src/assuan-io-pth.c
+++ b/src/assuan-io-pth.c
@@ -56,47 +56,24 @@ _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.  */
-  ssize_t retval;
-  
-  if (_assuan_io_hooks.read_hook
-      && _assuan_io_hooks.read_hook (ctx, ctx->inbound.fd, 
-                                     buffer, size, &retval) == 1)
-    return retval;
-
   return _assuan_io_read (ctx->inbound.fd, buffer, size);
 }
 
 ssize_t
 _assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size)
 {
-  ssize_t retval;
-  
-  if (_assuan_io_hooks.write_hook
-      && _assuan_io_hooks.write_hook (ctx, ctx->outbound.fd, 
-                                      buffer, size, &retval) == 1)
-    return retval;
   return _assuan_io_write (ctx->outbound.fd, buffer, size);
 }
 
 ssize_t
 _assuan_io_read (assuan_fd_t fd, void *buffer, size_t size)
 {
-  ssize_t retval;
-  
-  if (_assuan_io_hooks.read_hook
-      && _assuan_io_hooks.read_hook (NULL, fd, buffer, size, &retval) == 1)
-    return retval;
   return pth_read ((int)fd, buffer, size);
 }
 
 ssize_t
 _assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size)
 {
-  ssize_t retval;
-  
-  if (_assuan_io_hooks.write_hook
-      && _assuan_io_hooks.write_hook (NULL, fd, buffer, size, &retval) == 1)
-    return retval;
   return pth_write ((int)fd, buffer, size);
 }
 
diff --git a/src/assuan-io.c b/src/assuan-io.c
index 80e26ea..88accc3 100644
--- a/src/assuan-io.c
+++ b/src/assuan-io.c
@@ -95,25 +95,12 @@ do_io_read (assuan_fd_t fd, void *buffer, size_t size)
 ssize_t
 _assuan_io_read (assuan_fd_t fd, void *buffer, size_t size)
 {
-  ssize_t retval;
-  
-  if (_assuan_io_hooks.read_hook
-      && _assuan_io_hooks.read_hook (NULL, fd, buffer, size, &retval) == 1)
-    return retval;
-
   return do_io_read (fd, buffer, size);
 }
 
 ssize_t
 _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size)
 {
-  ssize_t retval;
-  
-  if (_assuan_io_hooks.read_hook
-      && _assuan_io_hooks.read_hook (ctx, ctx->inbound.fd, 
-                                     buffer, size, &retval) == 1)
-    return retval;
-
   return do_io_read (ctx->inbound.fd, buffer, size);
 }
 
@@ -156,24 +143,12 @@ do_io_write (assuan_fd_t fd, const void *buffer, size_t size)
 ssize_t
 _assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size)
 {
-  ssize_t retval;
-  
-  if (_assuan_io_hooks.write_hook
-      && _assuan_io_hooks.write_hook (NULL, fd, buffer, size, &retval) == 1)
-    return retval;
   return do_io_write (fd, buffer, size);
 }
 
 ssize_t
 _assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size)
 {
-  ssize_t retval;
-  
-  if (_assuan_io_hooks.write_hook
-      && _assuan_io_hooks.write_hook (ctx, ctx->outbound.fd, 
-                                      buffer, size, &retval) == 1)
-    return retval;
-
   return do_io_write (ctx->outbound.fd, buffer, size);
 }
 
diff --git a/src/assuan-listen.c b/src/assuan-listen.c
index 7a17181..3f57922 100644
--- a/src/assuan-listen.c
+++ b/src/assuan-listen.c
@@ -33,17 +33,17 @@ gpg_error_t
 assuan_set_hello_line (assuan_context_t ctx, const char *line)
 {
   if (!ctx)
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
   if (!line)
     {
-      _assuan_free (ctx->hello_line);
+      _assuan_free (ctx, ctx->hello_line);
       ctx->hello_line = NULL;
     }
   else
     {
-      char *buf = _assuan_malloc (3+strlen(line)+1);
+      char *buf = _assuan_malloc (ctx, 3 + strlen (line) + 1);
       if (!buf)
-	return _assuan_error (gpg_err_code_from_syserror ());
+	return _assuan_error (ctx, gpg_err_code_from_syserror ());
       if (strchr (line, '\n'))
         strcpy (buf, line);
       else
@@ -51,7 +51,7 @@ assuan_set_hello_line (assuan_context_t ctx, const char *line)
           strcpy (buf, "OK ");
           strcpy (buf+3, line);
         }
-      _assuan_free (ctx->hello_line);
+      _assuan_free (ctx, ctx->hello_line);
       ctx->hello_line = buf;
     }
   return 0;
@@ -76,7 +76,7 @@ assuan_accept (assuan_context_t ctx)
   const char *p, *pend;
 
   if (!ctx)
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
 
   if (ctx->pipe_mode > 1)
     return -1; /* second invocation for pipemode -> terminate */
@@ -137,7 +137,7 @@ gpg_error_t
 assuan_close_input_fd (assuan_context_t ctx)
 {
   if (!ctx || ctx->input_fd == ASSUAN_INVALID_FD)
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
   _assuan_close (ctx->input_fd);
   ctx->input_fd = ASSUAN_INVALID_FD;
   return 0;
@@ -149,7 +149,7 @@ gpg_error_t
 assuan_close_output_fd (assuan_context_t ctx)
 {
   if (!ctx || ctx->output_fd == ASSUAN_INVALID_FD)
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
 
   _assuan_close (ctx->output_fd);
   ctx->output_fd = ASSUAN_INVALID_FD;
diff --git a/src/assuan-logging.c b/src/assuan-logging.c
index 576f84a..0e57579 100644
--- a/src/assuan-logging.c
+++ b/src/assuan-logging.c
@@ -32,25 +32,17 @@
 
 #include "assuan-defs.h"
 
-static char prefix_buffer[80];
-static FILE *_assuan_log;
-static int full_logging;
+

+/* The default log handler is useful for global logging, but it should
+   only be used by one user of libassuan at a time.  Libraries that
+   use libassuan can register their own log handler.  */
 
-void
-_assuan_set_default_log_stream (FILE *fp)
-{
-  if (!_assuan_log)
-    {
-      _assuan_log = fp;
-      full_logging = !!getenv ("ASSUAN_FULL_LOGGING");
-    }
-}
+/* A common prefix for all log messages.  */
+static char prefix_buffer[80];
 
-void
-assuan_set_assuan_log_stream (FILE *fp)
-{
-  _assuan_log = fp;
-}
+/* A global flag read from the environment to check if to enable full
+   logging of buffer data.  */
+static int full_logging;
 
 
 /* Set the per context log stream.  Also enable the default log stream
@@ -63,20 +55,13 @@ assuan_set_log_stream (assuan_context_t ctx, FILE *fp)
       if (ctx->log_fp)
         fflush (ctx->log_fp);
       ctx->log_fp = fp;
-      _assuan_set_default_log_stream (fp);
+      full_logging = !!getenv ("ASSUAN_FULL_LOGGING");
     }
 }
 
 
-FILE *
-assuan_get_assuan_log_stream (void)
-{
-  return _assuan_log ? _assuan_log : stderr;
-}
-
-
-/* Set the prefix to be used for logging to TEXT or
-   resets it to the default if TEXT is NULL. */
+/* Set the prefix to be used for logging to TEXT or resets it to the
+   default if TEXT is NULL. */
 void
 assuan_set_assuan_log_prefix (const char *text)
 {
@@ -89,38 +74,48 @@ assuan_set_assuan_log_prefix (const char *text)
     *prefix_buffer = 0;
 }
 
+
+/* Get the prefix to be used for logging.  */
 const char *
 assuan_get_assuan_log_prefix (void)
 {
   return prefix_buffer;
 }
 
-
-void
-_assuan_log_printf (const char *format, ...)
+

+/* Default log handler.  */
+int
+_assuan_log_handler (assuan_context_t ctx, void *hook, unsigned int cat,
+		     const char *msg)
 {
-  va_list arg_ptr;
   FILE *fp;
   const char *prf;
-  int save_errno = errno;
-  
-  fp = assuan_get_assuan_log_stream ();
+  int saved_errno = errno;
+
+  /* For now.  */
+  if (msg == NULL)
+    return 1;
+
+  fp = ctx->log_fp;
+  if (!fp)
+    return 0;
+
   prf = assuan_get_assuan_log_prefix ();
   if (*prf)
     fprintf (fp, "%s[%u]: ", prf, (unsigned int)getpid ());
 
-  va_start (arg_ptr, format);
-  vfprintf (fp, format, arg_ptr );
-  va_end (arg_ptr);
+  fprintf (fp, "%s", msg);
   /* If the log stream is a file, the output would be buffered.  This
      is bad for debugging, thus we flush the stream if FORMAT ends
      with a LF.  */ 
-  if (format && *format && format[strlen(format)-1] == '\n')
+  if (msg && *msg && msg[strlen (msg) - 1] == '\n')
     fflush (fp);
-  errno = save_errno;
-}
+  errno = saved_errno;
 
+  return 0;
+}
 
+

 /* Dump a possibly binary string (used for debugging).  Distinguish
    ascii text from binary and print it accordingly.  This function
    takes FILE pointer arg because logging may be enabled on a per
@@ -162,84 +157,3 @@ _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length)
 #endif
     }
 }
-
-/* Log a user supplied string.  Escapes non-printable before
-   printing.  */
-void
-_assuan_log_sanitized_string (const char *string)
-{
-  const unsigned char *s = (const unsigned char *) string;
-  FILE *fp = assuan_get_assuan_log_stream ();
-
-  if (! *s)
-    return;
-
-#ifdef HAVE_FLOCKFILE
-  flockfile (fp);
-#endif
-
-  for (; *s; s++)
-    {
-      int c = 0;
-
-      switch (*s)
-	{
-	case '\r':
-	  c = 'r';
-	  break;
-
-	case '\n':
-	  c = 'n';
-	  break;
-
-	case '\f':
-	  c = 'f';
-	  break;
-
-	case '\v':
-	  c = 'v';
-	  break;
-
-	case '\b':
-	  c = 'b';
-	  break;
-
-	default:
-	  if ((isascii (*s) && isprint (*s)) || (*s >= 0x80))
-	    putc_unlocked (*s, fp);
-	  else
-	    {
-	      putc_unlocked ('\\', fp);
-	      fprintf (fp, "x%02x", *s);
-	    }
-	}
-
-      if (c)
-	{
-	  putc_unlocked ('\\', fp);
-	  putc_unlocked (c, fp);
-	}
-    }
-
-#ifdef HAVE_FUNLOCKFILE
-  funlockfile (fp);
-#endif
-}
-
-
-
-#ifdef HAVE_W32_SYSTEM
-const char *
-_assuan_w32_strerror (int ec)
-{
-  static char strerr[256];
-  
-  if (ec == -1)
-    ec = (int)GetLastError ();
-  FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec,
-                 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
-                 strerr, sizeof (strerr)-1, NULL);
-  return strerr;    
-}
-
-#endif /*HAVE_W32_SYSTEM*/
diff --git a/src/assuan-pipe-connect.c b/src/assuan-pipe-connect.c
index 92d3926..15b5232 100644
--- a/src/assuan-pipe-connect.c
+++ b/src/assuan-pipe-connect.c
@@ -36,6 +36,7 @@
 #endif
 
 #include "assuan-defs.h"
+#include "debug.h"
 
 /* Hacks for Slowaris.  */
 #ifndef PF_LOCAL
@@ -146,27 +147,22 @@ do_deinit (assuan_context_t ctx)
 
 /* Helper for pipe_connect. */
 static gpg_error_t
-initial_handshake (assuan_context_t *ctx)
+initial_handshake (assuan_context_t ctx)
 {
   int okay, off;
   gpg_error_t err;
   
-  err = _assuan_read_from_server (*ctx, &okay, &off);
+  err = _assuan_read_from_server (ctx, &okay, &off);
   if (err)
-    _assuan_log_printf ("can't connect server: %s\n",
-                        gpg_strerror (err));
+    TRACE1 (ctx, ASSUAN_LOG_SYSIO, "initial_handshake", ctx,
+	    "can't connect server: %s", gpg_strerror (err));
   else if (okay != 1)
     {
-      _assuan_log_printf ("can't connect server: `%s'\n",
-                          (*ctx)->inbound.line);
-      err = _assuan_error (GPG_ERR_ASS_CONNECT_FAILED);
+      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "initial_handshake", ctx,
+	      "can't connect server: `%s'", ctx->inbound.line);
+      err = _assuan_error (ctx, GPG_ERR_ASS_CONNECT_FAILED);
     }
 
-  if (err)
-    {
-      assuan_disconnect (*ctx);
-      *ctx = NULL;
-    }
   return err;
 }
 
@@ -176,70 +172,57 @@ initial_handshake (assuan_context_t *ctx)
 /* Unix version of the pipe connection code.  We use an extra macro to
    make ChangeLog entries easier. */
 static gpg_error_t
-pipe_connect_unix (assuan_context_t *ctx,
+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)
 {
-  gpg_error_t err;
   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 };
 
   (void)flags;
 
   if (!ctx || !name || !argv || !argv[0])
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
 
   fix_signals ();
 
   sprintf (mypidstr, "%lu", (unsigned long)getpid ());
 
   if (pipe (rp) < 0)
-    return _assuan_error (GPG_ERR_ASS_GENERAL);
+    return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);
   
   if (pipe (wp) < 0)
     {
       close (rp[0]);
       close (rp[1]);
-      return _assuan_error (GPG_ERR_ASS_GENERAL);
+      return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);
     }
 
-  err = _assuan_new_context (ctx);
-  if (err)
-    {
-      close (rp[0]);
-      close (rp[1]);
-      close (wp[0]);
-      close (wp[1]);
-      return err;
-    }
-  (*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;
-
   /* FIXME: For GPGME we should better use _gpgme_io_spawn.  The PID
      stored here is actually soon useless.  */
-  (*ctx)->pid = fork ();
-  if ((*ctx)->pid < 0)
+  pid = fork ();
+  if (pid < 0)
     {
       close (rp[0]);
       close (rp[1]);
       close (wp[0]);
       close (wp[1]);
-      _assuan_release_context (*ctx); 
-      return _assuan_error (GPG_ERR_ASS_GENERAL);
+      return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);
     }
 
-  if ((*ctx)->pid == 0)
+  if (pid == 0)
     {
 #ifdef _ASSUAN_USE_DOUBLE_FORK      
-      pid_t pid;
+      pid_t pid2;
 
-      if ((pid = fork ()) == 0)
+      if ((pid2 = fork ()) == 0)
 #endif
 	{
           int i, n;
@@ -254,8 +237,8 @@ pipe_connect_unix (assuan_context_t *ctx,
             {
               if (dup2 (rp[1], STDOUT_FILENO) == -1)
                 {
-                  _assuan_log_printf ("dup2 failed in child: %s\n",
-                                      strerror (errno));
+		  TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_unix", ctx,
+			  "dup2 failed in child: %s", strerror (errno));
                   _exit (4);
                 }
             }
@@ -263,8 +246,8 @@ pipe_connect_unix (assuan_context_t *ctx,
             {
               if (dup2 (wp[0], STDIN_FILENO) == -1)
                 {
-                  _assuan_log_printf ("dup2 failed in child: %s\n",
-                                      strerror (errno));
+		  TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_unix", ctx,
+			  "dup2 failed in child: %s", strerror (errno));
                   _exit (4);
                 }
             }
@@ -282,14 +265,14 @@ pipe_connect_unix (assuan_context_t *ctx,
               int fd = open ("/dev/null", O_WRONLY);
               if (fd == -1)
                 {
-                  _assuan_log_printf ("can't open `/dev/null': %s\n",
-                                      strerror (errno));
+		  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)
                 {
-                  _assuan_log_printf ("dup2(dev/null, 2) failed: %s\n",
-                                      strerror (errno));
+		  TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_unix", ctx,
+			  "dup2(dev/null, 2) failed: %s", strerror (errno));
                   _exit (4);
                 }
             }
@@ -332,14 +315,14 @@ pipe_connect_unix (assuan_context_t *ctx,
           /* 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 (GPG_ERR_ASS_SERVER_START),
+                    _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 (pid == -1)
+      if (pid2 == -1)
 	_exit (1);
       else
 	_exit (0);
@@ -347,14 +330,25 @@ pipe_connect_unix (assuan_context_t *ctx,
     }
 
 #ifdef _ASSUAN_USE_DOUBLE_FORK
-  _assuan_waitpid ((*ctx)->pid, NULL, 0);
-  (*ctx)->pid = -1;
+  _assuan_waitpid (pid, NULL, 0);
+  pid = -1;
 #endif
 
   close (rp[1]);
   close (wp[0]);
 
-  return initial_handshake (ctx);
+  ctx->io = &io;
+  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;
+
+  rc = initial_handshake (ctx);
+  if (rc)
+    _assuan_reset (ctx);
+  return rc;
 }
 #endif /*!HAVE_W32_SYSTEM*/
 
@@ -363,8 +357,8 @@ pipe_connect_unix (assuan_context_t *ctx,
 /* 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 *const argv[],
+socketpair_connect (assuan_context_t ctx,
+                    const char *name, const char *argv[],
                     int *fd_child_list,
                     void (*atfork) (void *opaque, int reserved),
                     void *atforkvalue)
@@ -372,11 +366,12 @@ socketpair_connect (assuan_context_t *ctx,
   gpg_error_t err;
   int fds[2];
   char mypidstr[50];
+  pid_t pid;
 
   if (!ctx
       || (name && (!argv || !argv[0]))
-      || (!name && argv))
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+      || (!name && !argv))
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
 
   fix_signals ();
 
@@ -384,40 +379,26 @@ socketpair_connect (assuan_context_t *ctx,
 
   if ( socketpair (AF_LOCAL, SOCK_STREAM, 0, fds) )
     {
-      _assuan_log_printf ("socketpair failed: %s\n", strerror (errno));
-      return _assuan_error (GPG_ERR_ASS_GENERAL);
+      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "socketpair_connect", ctx,
+	      "socketpair failed: %s", strerror (errno));
+      return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);
     }
-  
-  err = _assuan_new_context (ctx);
-  if (err)
-    {
-      close (fds[0]);
-      close (fds[1]);
-      return err;
-    }
-  (*ctx)->pipe_mode = 1;
-  (*ctx)->inbound.fd  = fds[0]; 
-  (*ctx)->outbound.fd = fds[0]; 
-  _assuan_init_uds_io (*ctx);
-  (*ctx)->deinit_handler = _assuan_uds_deinit;
-  (*ctx)->finish_handler = do_finish;
-
-  (*ctx)->pid = fork ();
-  if ((*ctx)->pid < 0)
+
+  pid = fork ();
+  if (pid < 0)
     {
       close (fds[0]);
       close (fds[1]);
-      _assuan_release_context (*ctx); 
-      *ctx = NULL;
-      return _assuan_error (GPG_ERR_ASS_GENERAL);
+      /* FIXME: cleanup ctx */
+      return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);
     }
 
-  if ((*ctx)->pid == 0)
+  if (pid == 0)
     {
 #ifdef _ASSUAN_USE_DOUBLE_FORK      
-      pid_t pid;
+      pid_t pid2;
 
-      if ((pid = fork ()) == 0)
+      if ((pid2 = fork ()) == 0)
 #endif
 	{
           int fd, i, n;
@@ -431,15 +412,15 @@ socketpair_connect (assuan_context_t *ctx,
           fd = open ("/dev/null", O_RDONLY);
           if (fd == -1 || dup2 (fd, STDIN_FILENO) == -1)
             {
-              _assuan_log_printf ("dup2(dev/null) failed: %s\n",
-                                  strerror (errno));
+	      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)
             {
-              _assuan_log_printf ("dup2(dev/null) failed: %s\n",
-                                  strerror (errno));
+	      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "socketpair_connect", ctx,
+		      "dup2(dev/null) failed: %s", strerror (errno));
               _exit (4);
             }
 
@@ -456,8 +437,8 @@ socketpair_connect (assuan_context_t *ctx,
               fd = open ("/dev/null", O_WRONLY);
               if (fd == -1 || dup2 (fd, STDERR_FILENO) == -1)
                 {
-                  _assuan_log_printf ("dup2(dev/null) failed: %s\n",
-                                      strerror (errno));
+		  TRACE1 (ctx, ASSUAN_LOG_SYSIO, "socketpair_connect", ctx,
+			  "dup2(dev/null) failed: %s", strerror (errno));
                   _exit (4);
                 }
             }
@@ -497,46 +478,60 @@ socketpair_connect (assuan_context_t *ctx,
           sprintf (mypidstr, "%d", fds[1]);
           if (setenv ("_assuan_connection_fd", mypidstr, 1))
             {
-              _assuan_log_printf ("setenv failed: %s\n", strerror (errno));
+	      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "socketpair_connect", ctx,
+		      "setenv failed: %s", strerror (errno));
               _exit (4);
             }
 
-          if (!name && !argv)
+          if (!name)
             {
               /* No name and no args given, thus we don't do an exec
                  but continue the forked process.  */
-              _assuan_release_context (*ctx);
-              *ctx = NULL;
-              return 0;
+	      *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 (GPG_ERR_ASS_SERVER_START),
+                    _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 (pid == -1)
+      if (pid2 == -1)
 	_exit (1);
       else
 	_exit (0);
 #endif
     }
 
+  if (! name)
+    *argv = "client";
 
 #ifdef _ASSUAN_USE_DOUBLE_FORK
-  _assuan_waitpid ((*ctx)->pid, NULL, 0);
-  (*ctx)->pid = -1;
+  _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]; 
+  ctx->deinit_handler = _assuan_uds_deinit;
+  ctx->finish_handler = do_finish;
+  _assuan_init_uds_io (ctx);
   
-  return initial_handshake (ctx);
+  err = initial_handshake (ctx);
+  if (err)
+    _assuan_reset (ctx);
+  return err;
 }
 #endif /*!HAVE_W32_SYSTEM*/
 
@@ -598,7 +593,8 @@ build_w32_commandline (const char * const *argv, char **cmdline)
 #ifdef HAVE_W32_SYSTEM
 /* Create pipe where one end end is inheritable.  */
 static int
-create_inheritable_pipe (assuan_fd_t filedes[2], int for_write)
+create_inheritable_pipe (assuan_context_t ctx,
+			 assuan_fd_t filedes[2], int for_write)
 {
   HANDLE r, w, h;
   SECURITY_ATTRIBUTES sec_attr;
@@ -609,7 +605,8 @@ create_inheritable_pipe (assuan_fd_t filedes[2], int for_write)
     
   if (!CreatePipe (&r, &w, &sec_attr, 0))
     {
-      _assuan_log_printf ("CreatePipe failed: %s\n", w32_strerror (-1));
+      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "create_inheritable_pipe", ctx,
+	      "CreatePipe failed: %s", w32_strerror (ctx, -1));
       return -1;
     }
 
@@ -617,7 +614,8 @@ create_inheritable_pipe (assuan_fd_t filedes[2], int for_write)
                         GetCurrentProcess(), &h, 0,
                         TRUE, DUPLICATE_SAME_ACCESS ))
     {
-      _assuan_log_printf ("DuplicateHandle failed: %s\n", w32_strerror (-1));
+      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "create_inheritable_pipe", ctx,
+	      "DuplicateHandle failed: %s", w32_strerror (ctx, -1));
       CloseHandle (r);
       CloseHandle (w);
       return -1;
@@ -644,7 +642,7 @@ create_inheritable_pipe (assuan_fd_t filedes[2], int for_write)
 #define pipe_connect pipe_connect_w32
 /* W32 version of the pipe connection code. */
 static gpg_error_t
-pipe_connect_w32 (assuan_context_t *ctx,
+pipe_connect_w32 (assuan_context_t ctx,
                   const char *name, const char *const argv[],
                   int *fd_child_list,
                   void (*atfork) (void *opaque, int reserved),
@@ -666,9 +664,11 @@ pipe_connect_w32 (assuan_context_t *ctx,
   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 (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
 
   fix_signals ();
 
@@ -676,41 +676,23 @@ pipe_connect_w32 (assuan_context_t *ctx,
 
   /* Build the command line.  */
   if (build_w32_commandline (argv, &cmdline))
-    return _assuan_error (gpg_err_code_from_syserror ());
+    return _assuan_error (ctx, gpg_err_code_from_syserror ());
 
   /* Create thew two pipes. */
-  if (create_inheritable_pipe (rp, 0))
+  if (create_inheritable_pipe (ctx, rp, 0))
     {
       _assuan_free (cmdline);
-      return _assuan_error (GPG_ERR_ASS_GENERAL);
+      return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);
     }
   
-  if (create_inheritable_pipe (wp, 1))
+  if (create_inheritable_pipe (ctx, wp, 1))
     {
       CloseHandle (rp[0]);
       CloseHandle (rp[1]);
       _assuan_free (cmdline);
-      return _assuan_error (GPG_ERR_ASS_GENERAL);
+      return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);
     }
 
-  
-  err = _assuan_new_context (ctx);
-  if (err)
-    {
-      CloseHandle (rp[0]);
-      CloseHandle (rp[1]);
-      CloseHandle (wp[0]);
-      CloseHandle (wp[1]);
-      _assuan_free (cmdline);
-      return _assuan_error (GPG_ERR_ASS_GENERAL);
-    }
-
-  (*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;
-
 
   /* fixme: Actually we should set the "_assuan_pipe_connect_pid" env
      variable.  However this requires us to write a full environment
@@ -746,13 +728,14 @@ pipe_connect_w32 (assuan_context_t *ctx,
                            NULL, OPEN_EXISTING, 0, NULL);
       if (nullfd == INVALID_HANDLE_VALUE)
         {
-          _assuan_log_printf ("can't open `nul': %s\n", w32_strerror (-1));
+	  TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_w32", ctx,
+		  "can't open `nul': %s", w32_strerror (ctx, -1));
           CloseHandle (rp[0]);
           CloseHandle (rp[1]);
           CloseHandle (wp[0]);
           CloseHandle (wp[1]);
           _assuan_free (cmdline);
-          _assuan_release_context (*ctx); 
+	  /* FIXME: Cleanup?  */
           return -1;
         }
       si.hStdError = nullfd;
@@ -781,7 +764,8 @@ pipe_connect_w32 (assuan_context_t *ctx,
                       &pi                   /* Returns process information.  */
                       ))
     {
-      _assuan_log_printf ("CreateProcess failed: %s\n", w32_strerror (-1));
+      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_w32", ctx,
+	      "CreateProcess failed: %s", w32_strerror (ctx, -1));
       CloseHandle (rp[0]);
       CloseHandle (rp[1]);
       CloseHandle (wp[0]);
@@ -789,8 +773,8 @@ pipe_connect_w32 (assuan_context_t *ctx,
       if (nullfd != INVALID_HANDLE_VALUE)
         CloseHandle (nullfd);
       _assuan_free (cmdline);
-      _assuan_release_context (*ctx); 
-      return _assuan_error (GPG_ERR_ASS_GENERAL);
+      /* FIXME: Cleanup?  */
+      return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);
     }
   _assuan_free (cmdline);
   cmdline = NULL;
@@ -810,9 +794,20 @@ pipe_connect_w32 (assuan_context_t *ctx,
 
   ResumeThread (pi.hThread);
   CloseHandle (pi.hThread); 
-  (*ctx)->pid = (pid_t) pi.hProcess;
 
-  return initial_handshake (ctx);
+  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*/
 
@@ -822,8 +817,8 @@ pipe_connect_w32 (assuan_context_t *ctx,
    vector in ARGV.  FD_CHILD_LIST is a -1 terminated list of file
    descriptors not to close in the child.  */
 gpg_error_t
-assuan_pipe_connect (assuan_context_t *ctx, const char *name,
-		     const char *const argv[], int *fd_child_list)
+assuan_pipe_connect (assuan_context_t ctx, const char *name,
+		     const char *argv[], int *fd_child_list)
 {
   return pipe_connect (ctx, name, argv, fd_child_list, NULL, NULL, 0);
 }
@@ -852,14 +847,15 @@ assuan_pipe_connect (assuan_context_t *ctx, const char *name,
           console window when starting the server
 
 
-   If NAME as well as ARGV are NULL, no exec is done but the same
-   process is continued.  However all file descriptors are closed and
-   some special environment variables are set. To let the caller
-   detect whether the child or the parent continues, the child returns
-   a CTX of NULL. */
+   If NAME is NULL, no exec is done but the same process is continued.
+   However all file descriptors are closed and some special
+   environment variables are set. To let the caller detect whether the
+   child or the parent continues, the child returns "client" or
+   "server" in *ARGV (but it is sufficient to check only the first
+   character).  */
 gpg_error_t
-assuan_pipe_connect_ext (assuan_context_t *ctx,
-                         const char *name, const char *const argv[],
+assuan_pipe_connect_ext (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)
@@ -867,7 +863,7 @@ assuan_pipe_connect_ext (assuan_context_t *ctx,
   if ((flags & 1))
     {
 #ifdef HAVE_W32_SYSTEM
-      return _assuan_error (GPG_ERR_NOT_IMPLEMENTED);
+      return _assuan_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
 #else
       return socketpair_connect (ctx, name, argv, fd_child_list,
                                  atfork, atforkvalue);
@@ -877,4 +873,3 @@ 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 a732db7..3c30d48 100644
--- a/src/assuan-pipe-server.c
+++ b/src/assuan-pipe-server.c
@@ -47,48 +47,10 @@ accept_connection (assuan_context_t ctx)
   return 0;
 }
 
-static gpg_error_t
+static void
 finish_connection (assuan_context_t ctx)
 {
   /* This is a NOP for a pipe server */
-  return 0;
-}
-
-/* Create a new context.  Note that the handlers are set up for a pipe
-   server/client - this way we don't need extra dummy functions */
-gpg_error_t
-_assuan_new_context (assuan_context_t *r_ctx)
-{
-  static struct assuan_io io = { _assuan_simple_read,
-				 _assuan_simple_write,
-				 0, 0 };
-
-  assuan_context_t ctx;
-  gpg_error_t rc;
-
-  *r_ctx = NULL;
-  ctx = _assuan_calloc (1, sizeof *ctx);
-  if (!ctx)
-    return _assuan_error (gpg_err_code_from_syserror ());
-  ctx->input_fd = ASSUAN_INVALID_FD;
-  ctx->output_fd = ASSUAN_INVALID_FD;
-
-  ctx->inbound.fd = ASSUAN_INVALID_FD;
-  ctx->outbound.fd = ASSUAN_INVALID_FD;
-  ctx->io = &io;
-
-  ctx->listen_fd = ASSUAN_INVALID_FD;
-  /* Use the pipe server handler as a default.  */
-  ctx->deinit_handler = deinit_pipe_server;
-  ctx->accept_handler = accept_connection;
-  ctx->finish_handler = finish_connection;
-
-  rc = _assuan_register_std_commands (ctx);
-  if (rc)
-    _assuan_free (ctx);
-  else
-    *r_ctx = ctx;
-  return rc;
 }
 
 
@@ -107,86 +69,92 @@ is_valid_socket (const char *s)
 
 
 gpg_error_t
-assuan_init_pipe_server (assuan_context_t *r_ctx, int filedes[2])
+assuan_init_pipe_server (assuan_context_t ctx, int filedes[2])
 {
-  int rc;
+  const char *s;
+  unsigned long ul;
+  gpg_error_t rc;
+  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_new_context (r_ctx);
-  if (!rc)
-    {
-      assuan_context_t ctx = *r_ctx;
-      const char *s;
-      unsigned long ul;
+  rc = _assuan_register_std_commands (ctx);
+  if (rc)
+    return rc;
 
-      ctx->is_server = 1;
 #ifdef HAVE_W32_SYSTEM
-      /* MS Windows has so many different types of handle that one
-         needs to tranlsate them at many place forth and back.  Also
-         make sure that the file descriptors are in binary mode.  */
-      setmode (filedes[0], O_BINARY);
-      setmode (filedes[1], O_BINARY);
-      ctx->inbound.fd  = (void*)_get_osfhandle (filedes[0]);
-      ctx->outbound.fd = (void*)_get_osfhandle (filedes[1]);
+  /* MS Windows has so many different types of handle that one needs
+     to tranlsate them at many place forth and back.  Also make sure
+     that the file descriptors are in binary mode.  */
+  setmode (filedes[0], O_BINARY);
+  setmode (filedes[1], O_BINARY);
+  infd  = (void*)_get_osfhandle (filedes[0]);
+  outfd = (void*)_get_osfhandle (filedes[1]);
 #else
-      s = getenv ("_assuan_connection_fd");
-      if (s && *s && is_valid_socket (s) )
-        {
-          /* Well, we are called with an bi-directional file
-             descriptor.  Prepare for using sendmsg/recvmsg.  In this
-             case we ignore the passed file descriptors. */
-          ctx->inbound.fd  = ctx->outbound.fd = atoi (s);
-          _assuan_init_uds_io (ctx);
-          ctx->deinit_handler = _assuan_uds_deinit;
-        }
-      else if (filedes && filedes[0] != ASSUAN_INVALID_FD 
-               && filedes[1] != ASSUAN_INVALID_FD )
-        {
-          /* Standard pipe server. */
-          ctx->inbound.fd  = filedes[0];
-          ctx->outbound.fd = filedes[1];
-        }
-      else
-        {
-          _assuan_release_context (*r_ctx);
-          *r_ctx = NULL;
-          return _assuan_error (GPG_ERR_ASS_SERVER_START);
-        }
-#endif
-      ctx->pipe_mode = 1;
-
-      s = getenv ("_assuan_pipe_connect_pid");
-      if (s && (ul=strtoul (s, NULL, 10)) && ul)
-        ctx->pid = (pid_t)ul;
-      else
-        ctx->pid = (pid_t)-1;
+  s = getenv ("_assuan_connection_fd");
+  if (s && *s && is_valid_socket (s))
+    {
+      /* Well, we are called with an bi-directional file descriptor.
+	 Prepare for using sendmsg/recvmsg.  In this case we ignore
+	 the passed file descriptors. */
+      infd = atoi (s);
+      outfd = atoi (s);
+      is_usd = 1;
 
     }
-  return rc;
-}
+  else if (filedes && filedes[0] != ASSUAN_INVALID_FD 
+	   && filedes[1] != ASSUAN_INVALID_FD )
+    {
+      /* Standard pipe server. */
+      infd = filedes[0];
+      outfd = filedes[1];
+    }
+  else
+    return _assuan_error (ctx, GPG_ERR_ASS_SERVER_START);
+#endif
 
+  ctx->is_server = 1;
+  ctx->engine.release = deinit_pipe_server;
+  ctx->pipe_mode = 1;
 
-void
-_assuan_release_context (assuan_context_t ctx)
-{
-  if (ctx)
+  s = getenv ("_assuan_pipe_connect_pid");
+  if (s && (ul=strtoul (s, NULL, 10)) && ul)
+    ctx->pid = (pid_t)ul;
+  else
+    ctx->pid = (pid_t)-1;
+  ctx->accept_handler = accept_connection;
+  ctx->finish_handler = finish_connection;
+  ctx->deinit_handler = deinit_pipe_server;
+  ctx->inbound.fd = infd;
+  ctx->outbound.fd = outfd;
+
+  if (is_usd)
     {
-      _assuan_inquire_release (ctx);
-      _assuan_free (ctx->hello_line);
-      _assuan_free (ctx->okay_line);
-      _assuan_free (ctx->cmdtbl);
-      _assuan_free (ctx);
+      _assuan_init_uds_io (ctx);
+      ctx->deinit_handler = _assuan_uds_deinit;
     }
+  else
+    ctx->io = &io;
+
+  return 0;
 }
 
+
 void
-assuan_deinit_server (assuan_context_t ctx)
+_assuan_deinit_server (assuan_context_t ctx)
 {
-  if (ctx)
-    {
-      /* We use this function pointer to avoid linking other server
-         when not needed but still allow for a generic deinit function.  */
-      ctx->deinit_handler (ctx);
-      ctx->deinit_handler = NULL;
-      _assuan_release_context (ctx);
-    }
+  /* We use this function pointer to avoid linking other server when
+     not needed but still allow for a generic deinit function.  */
+  ctx->deinit_handler (ctx);
+  ctx->deinit_handler = NULL;
+ 
+  _assuan_inquire_release (ctx);
+  _assuan_free (ctx, ctx->hello_line);
+  ctx->hello_line = NULL;
+  _assuan_free (ctx, ctx->okay_line);
+  ctx->okay_line = NULL;
+  _assuan_free (ctx, ctx->cmdtbl);
+  ctx->cmdtbl = NULL;
 }
diff --git a/src/assuan-socket-connect.c b/src/assuan-socket-connect.c
index 8a8cb92..ac2df5b 100644
--- a/src/assuan-socket-connect.c
+++ b/src/assuan-socket-connect.c
@@ -33,6 +33,7 @@
 #endif
 
 #include "assuan-defs.h"
+#include "debug.h"
 
 /* Hacks for Slowaris.  */
 #ifndef PF_LOCAL
@@ -52,18 +53,22 @@
 #endif
 
  
-static int
+static void
 do_finish (assuan_context_t ctx)
 {
   if (ctx->inbound.fd != ASSUAN_INVALID_FD)
     {
       _assuan_close (ctx->inbound.fd);
+      ctx->inbound.fd = ASSUAN_INVALID_FD;
+    }
+  if (ctx->outbound.fd != ASSUAN_INVALID_FD)
+    {
+      _assuan_close (ctx->outbound.fd);
+      ctx->outbound.fd = ASSUAN_INVALID_FD;
     }
-  ctx->inbound.fd = ASSUAN_INVALID_FD;
-  ctx->outbound.fd = ASSUAN_INVALID_FD;
-  return 0;
 }
 
+
 static void
 do_deinit (assuan_context_t ctx)
 {
@@ -75,10 +80,10 @@ do_deinit (assuan_context_t ctx)
    Assuan context in CTX.  SERVER_PID is currently not used but may
    become handy in the future.  */
 gpg_error_t
-assuan_socket_connect (assuan_context_t *r_ctx,
+assuan_socket_connect (assuan_context_t ctx,
                        const char *name, pid_t server_pid)
 {
-  return assuan_socket_connect_ext (r_ctx, name, server_pid, 0);
+  return assuan_socket_connect_ext (ctx, name, server_pid, 0);
 }
 
 
@@ -87,22 +92,21 @@ assuan_socket_connect (assuan_context_t *r_ctx,
    become handy in the future.  With flags set to 1 sendmsg and
    recvmsg are used. */
 gpg_error_t
-assuan_socket_connect_ext (assuan_context_t *r_ctx,
+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_context_t ctx;
   assuan_fd_t fd;
   struct sockaddr_un srvr_addr;
   size_t len;
   const char *s;
 
-  if (!r_ctx || !name)
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
-  *r_ctx = NULL;
+
+  if (!ctx || !name)
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
 
   /* We require that the name starts with a slash, so that we
      eventually can reuse this function for other socket types.  To
@@ -111,23 +115,18 @@ assuan_socket_connect_ext (assuan_context_t *r_ctx,
   if (*s && s[1] == ':')
     s += 2;
   if (*s != DIRSEP_C && *s != '/')
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
 
   if (strlen (name)+1 >= sizeof srvr_addr.sun_path)
-    return _assuan_error (GPG_ERR_ASS_INV_VALUE);
-
-  err = _assuan_new_context (&ctx); 
-  if (err)
-      return err;
-  ctx->deinit_handler = ((flags&1))? _assuan_uds_deinit :  do_deinit;
-  ctx->finish_handler = do_finish;
+    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
 
   fd = _assuan_sock_new (PF_LOCAL, SOCK_STREAM, 0);
   if (fd == ASSUAN_INVALID_FD)
     {
-      _assuan_log_printf ("can't create socket: %s\n", strerror (errno));
-      _assuan_release_context (ctx);
-      return _assuan_error (GPG_ERR_ASS_GENERAL);
+      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "assuan_socket_connect_ext", ctx,
+	      "can't create socket: %s", strerror (errno));
+      /* FIXME: Cleanup  */
+      return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);
     }
 
   memset (&srvr_addr, 0, sizeof srvr_addr);
@@ -138,43 +137,46 @@ assuan_socket_connect_ext (assuan_context_t *r_ctx,
 
   if ( _assuan_sock_connect (fd, (struct sockaddr *) &srvr_addr, len) == -1 )
     {
-      _assuan_log_printf ("can't connect to `%s': %s\n",
-                          name, strerror (errno));
-      _assuan_release_context (ctx);
+      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);
-      return _assuan_error (GPG_ERR_ASS_CONNECT_FAILED);
+      return _assuan_error (ctx, GPG_ERR_ASS_CONNECT_FAILED);
     }
-
+ 
+  ctx->io = &io;
+  ctx->engine.release = _assuan_disconnect;
+  ctx->deinit_handler = ((flags&1))? _assuan_uds_deinit :  do_deinit;
+  ctx->finish_handler = do_finish;
   ctx->inbound.fd = fd;
   ctx->outbound.fd = fd;
-  ctx->io = &io;
-  if ((flags&1))
+
+  if (flags & 1)
     _assuan_init_uds_io (ctx);
- 
+
   /* initial handshake */
   {
     int okay, off;
 
     err = _assuan_read_from_server (ctx, &okay, &off);
     if (err)
-      _assuan_log_printf ("can't connect to server: %s\n",
-                          gpg_strerror (err));
+      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "assuan_socket_connect_ext", ctx,
+	      "can't connect to server: %s\n", gpg_strerror (err));
     else if (okay != 1)
       {
-        /*LOG ("can't connect to server: `");*/
-	_assuan_log_sanitized_string (ctx->inbound.line);
-	fprintf (assuan_get_assuan_log_stream (), "'\n");
-	err = _assuan_error (GPG_ERR_ASS_CONNECT_FAILED);
+	char *sname = _assuan_encode_c_string (ctx, ctx->inbound.line);
+	if (sname)
+	  {
+	    TRACE1 (ctx, ASSUAN_LOG_SYSIO, "assuan_socket_connect_ext", ctx,
+		    "can't connect to server: %s", sname);
+	    _assuan_free (ctx, sname);
+	  }
+	err = _assuan_error (ctx, GPG_ERR_ASS_CONNECT_FAILED);
       }
   }
-
+  
   if (err)
-    {
-      assuan_disconnect (ctx); 
-    }
-  else
-    *r_ctx = ctx;
-  return 0;
-}
-
+    _assuan_reset (ctx);
 
+  return err;
+}
diff --git a/src/assuan-socket-server.c b/src/assuan-socket-server.c
index a205b9e..b46a4e7 100644
--- a/src/assuan-socket-server.c
+++ b/src/assuan-socket-server.c
@@ -41,9 +41,6 @@
 
 #include "assuan-defs.h"
 
-static struct assuan_io io = { _assuan_simple_read, _assuan_simple_write,
-			       NULL, NULL };
-
 static gpg_error_t
 accept_connection_bottom (assuan_context_t ctx)
 {
@@ -80,7 +77,7 @@ accept_connection_bottom (assuan_context_t ctx)
   ctx->outbound.data.linelen = 0;
   ctx->outbound.data.error = 0;
   
-  ctx->confidential = 0;
+  ctx->flags.confidential = 0;
 
   return 0;
 }
@@ -97,28 +94,32 @@ accept_connection (assuan_context_t ctx)
                              (struct sockaddr*)&clnt_addr, &len ));
   if (fd == ASSUAN_INVALID_FD)
     {
-      return _assuan_error (gpg_err_code_from_syserror ());
+      return _assuan_error (ctx, gpg_err_code_from_syserror ());
     }
   if (_assuan_sock_check_nonce (fd, &ctx->listen_nonce))
     {
       _assuan_close (fd);
-      return _assuan_error (GPG_ERR_ASS_ACCEPT_FAILED);
+      return _assuan_error (ctx, GPG_ERR_ASS_ACCEPT_FAILED);
     }
 
   ctx->connected_fd = fd;
   return accept_connection_bottom (ctx);
 }
 
-static gpg_error_t
+
+static void
 finish_connection (assuan_context_t ctx)
 {
   if (ctx->inbound.fd != ASSUAN_INVALID_FD)
     {
       _assuan_close (ctx->inbound.fd);
+      ctx->inbound.fd = ASSUAN_INVALID_FD;
+    }
+  if (ctx->outbound.fd != ASSUAN_INVALID_FD)
+    {
+      _assuan_close (ctx->outbound.fd);
+      ctx->outbound.fd = ASSUAN_INVALID_FD;
     }
-  ctx->inbound.fd = ASSUAN_INVALID_FD;
-  ctx->outbound.fd = ASSUAN_INVALID_FD;
-  return 0;
 }
 
 
@@ -126,14 +127,22 @@ static void
 deinit_socket_server (assuan_context_t ctx)
 {
   finish_connection (ctx);
+
+  _assuan_inquire_release (ctx);
+  _assuan_free (ctx, ctx->hello_line);
+  ctx->hello_line = NULL;
+  _assuan_free (ctx, ctx->okay_line);
+  ctx->okay_line = NULL;
+  _assuan_free (ctx, ctx->cmdtbl);
+  ctx->cmdtbl = NULL;
 }
 
 /* Initialize a server for the socket LISTEN_FD which has already be
    put into listen mode */
 gpg_error_t
-assuan_init_socket_server (assuan_context_t *r_ctx, assuan_fd_t listen_fd)
+assuan_init_socket_server (assuan_context_t ctx, assuan_fd_t listen_fd)
 {
-  return assuan_init_socket_server_ext (r_ctx, listen_fd, 0);
+  return assuan_init_socket_server_ext (ctx, listen_fd, 0);
 }
 
 
@@ -142,18 +151,21 @@ assuan_init_socket_server (assuan_context_t *r_ctx, assuan_fd_t listen_fd)
               1 - FD has already been accepted.
 */
 gpg_error_t
-assuan_init_socket_server_ext (assuan_context_t *r_ctx, assuan_fd_t fd,
+assuan_init_socket_server_ext (assuan_context_t ctx, assuan_fd_t fd,
                                unsigned int flags)
 {
-  assuan_context_t ctx;
-  int rc;
+  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;
 
-  *r_ctx = NULL;
-  ctx = _assuan_calloc (1, sizeof *ctx);
-  if (!ctx)
-    return _assuan_error (gpg_err_code_from_syserror ());
+  ctx->io = &io;
+  ctx->engine.release = deinit_socket_server;
   ctx->is_server = 1;
-  if ((flags & 2))
+  if (flags & 2)
     ctx->pipe_mode = 1; /* We want a second accept to indicate EOF. */
   ctx->input_fd = ASSUAN_INVALID_FD;
   ctx->output_fd = ASSUAN_INVALID_FD;
@@ -177,15 +189,12 @@ assuan_init_socket_server_ext (assuan_context_t *r_ctx, assuan_fd_t fd,
                          : accept_connection);
   ctx->finish_handler = finish_connection;
 
-  ctx->io = &io;
   if ((flags & 1))
     _assuan_init_uds_io (ctx);
 
   rc = _assuan_register_std_commands (ctx);
   if (rc)
-    _assuan_free (ctx);
-  else
-    *r_ctx = ctx;
+    _assuan_reset (ctx);
   return rc;
 }
 
diff --git a/src/assuan-uds.c b/src/assuan-uds.c
index 9497992..1c2d106 100644
--- a/src/assuan-uds.c
+++ b/src/assuan-uds.c
@@ -41,6 +41,7 @@
 #include <assert.h>
 
 #include "assuan-defs.h"
+#include "debug.h"
 
 #ifdef USE_DESCRIPTOR_PASSING
 /* Provide replacement for missing CMSG maccros.  We assume that
@@ -75,7 +76,7 @@ uds_reader (assuan_context_t ctx, void *buf, size_t buflen)
 
   if (!ctx->uds.bufferallocated)
     {
-      ctx->uds.buffer = _assuan_malloc (2048);
+      ctx->uds.buffer = _assuan_malloc (ctx, 2048);
       if (!ctx->uds.buffer)
         return gpg_error_from_syserror ();
       ctx->uds.bufferallocated = 2048;
@@ -121,15 +122,17 @@ uds_reader (assuan_context_t ctx, void *buf, size_t buflen)
         {
           if (cmptr->cmsg_level != SOL_SOCKET
               || cmptr->cmsg_type != SCM_RIGHTS)
-            _assuan_log_printf ("unexpected ancillary data received\n");
+            TRACE0 (ctx, ASSUAN_LOG_SYSIO, "uds_reader", ctx,
+		    "unexpected ancillary data received");
           else
             {
               int fd = *((int*)CMSG_DATA (cmptr));
 
               if (ctx->uds.pendingfdscount >= DIM (ctx->uds.pendingfds))
                 {
-                  _assuan_log_printf ("too many descriptors pending - "
-                                      "closing received descriptor %d\n", fd);
+		  TRACE1 (ctx, ASSUAN_LOG_SYSIO, "uds_reader", ctx,
+			  "too many descriptors pending - "
+			  "closing received descriptor %d", fd);
                   _assuan_close (fd);
                 }
               else
@@ -232,14 +235,15 @@ uds_sendfd (assuan_context_t ctx, assuan_fd_t fd)
   if (len < 0)
     {
       int saved_errno = errno;
-      _assuan_log_printf ("uds_sendfd: %s\n", strerror (errno));
+      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "uds_sendfd", ctx,
+	      "uds_sendfd: %s", strerror (errno));
       errno = saved_errno;
-      return _assuan_error (gpg_err_code_from_syserror ());
+      return _assuan_error (ctx, gpg_err_code_from_syserror ());
     }
   else
     return 0;
 #else
-  return _assuan_error (GPG_ERR_NOT_IMPLEMENTED);
+  return _assuan_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
 #endif
 }
 
@@ -252,8 +256,9 @@ uds_receivefd (assuan_context_t ctx, assuan_fd_t *fd)
 
   if (!ctx->uds.pendingfdscount)
     {
-      _assuan_log_printf ("no pending file descriptors!\n");
-      return _assuan_error (GPG_ERR_ASS_GENERAL);
+      TRACE0 (ctx, ASSUAN_LOG_SYSIO, "uds_receivefd", ctx,
+	      "no pending file descriptors");
+      return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);
     }
   assert (ctx->uds.pendingfdscount <= DIM(ctx->uds.pendingfds));
 
@@ -264,7 +269,7 @@ uds_receivefd (assuan_context_t ctx, assuan_fd_t *fd)
 
   return 0;
 #else
-  return _assuan_error (GPG_ERR_NOT_IMPLEMENTED);
+  return _assuan_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
 #endif
 }
 
@@ -291,7 +296,7 @@ _assuan_uds_deinit (assuan_context_t ctx)
     {
       assert (ctx->uds.bufferallocated);
       ctx->uds.bufferallocated = 0;
-      _assuan_free (ctx->uds.buffer);
+      _assuan_free (ctx, ctx->uds.buffer);
     }
 
   _assuan_uds_close_fds (ctx);
diff --git a/src/assuan-util.c b/src/assuan-util.c
index e12b44e..e69de29 100644
--- a/src/assuan-util.c
+++ b/src/assuan-util.c
@@ -1,190 +0,0 @@
-/* assuan-util.c - Utility functions for Assuan 
-   Copyright (C) 2001-2005, 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 <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include "assuan-defs.h"
-
-static void *(*alloc_func)(size_t n) = malloc;
-static void *(*realloc_func)(void *p, size_t n) = realloc;
-static void (*free_func)(void*) = free;
-
-struct assuan_io_hooks _assuan_io_hooks;
-
-
-void
-assuan_set_malloc_hooks (void *(*new_alloc_func)(size_t n),
-                         void *(*new_realloc_func)(void *p, size_t n),
-                         void (*new_free_func)(void*))
-{
-  alloc_func	    = new_alloc_func;
-  realloc_func      = new_realloc_func;
-  free_func	    = new_free_func;
-}
-
-
-void
-assuan_set_io_hooks (assuan_io_hooks_t io_hooks)
-{
-  _assuan_io_hooks.read_hook = NULL;
-  _assuan_io_hooks.write_hook = NULL;
-  if (io_hooks)
-    {
-      _assuan_io_hooks.read_hook = io_hooks->read_hook;
-      _assuan_io_hooks.write_hook = io_hooks->write_hook;
-    }
-}
-
-
-void *
-_assuan_malloc (size_t n)
-{
-  return alloc_func (n);
-}
-
-void *
-_assuan_realloc (void *a, size_t n)
-{
-  return realloc_func (a, n);
-}
-
-void *
-_assuan_calloc (size_t n, size_t m)
-{
-  void *p;
-  size_t nbytes;
-    
-  nbytes = n * m;
-  if (m && nbytes / m != n) 
-    {
-      errno = ENOMEM;
-      return NULL;
-    }
-
-  p = _assuan_malloc (nbytes);
-  if (p)
-    memset (p, 0, nbytes);
-  return p;
-}
-
-void
-_assuan_free (void *p)
-{
-  if (p)
-    free_func (p);
-}
-
-

-/* Store the error in the context so that the error sending function
-  can take out a descriptive text.  Inside the assuan code, use the
-  macro set_error instead of this function. */
-gpg_error_t
-assuan_set_error (assuan_context_t ctx, gpg_error_t err, const char *text)
-{
-  ctx->err_no = err;
-  ctx->err_str = text;
-  return err;
-}
-
-void
-assuan_set_pointer (assuan_context_t ctx, void *pointer)
-{
-  if (ctx)
-    ctx->user_pointer = pointer;
-}
-
-void *
-assuan_get_pointer (assuan_context_t ctx)
-{
-  return ctx? ctx->user_pointer : NULL;
-}
-
-
-void
-assuan_begin_confidential (assuan_context_t ctx)
-{
-  if (ctx)
-    {
-      ctx->confidential = 1;
-    }
-}
-
-void
-assuan_end_confidential (assuan_context_t ctx)
-{
-  if (ctx)
-    {
-      ctx->confidential = 0;
-    }
-}
-
-
-void 
-assuan_set_io_monitor (assuan_context_t ctx,
-                       unsigned int (*monitor)(assuan_context_t ctx,
-                                               int direction,
-                                               const char *line,
-                                               size_t linelen))
-{
-  if (ctx)
-    {
-      ctx->io_monitor = monitor;
-    }
-}
-
-
-
-
-/* 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;
-   see the description of the type assuan_flag_t for details. */
-void
-assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value)
-{
-  if (!ctx)
-    return;
-  switch (flag)
-    {
-    case ASSUAN_NO_WAITPID: ctx->flags.no_waitpid = value; break;
-    case ASSUAN_CONFIDENTIAL: ctx->confidential = value; break;
-    }
-}
-
-/* Return the VALUE of FLAG in context CTX. */ 
-int
-assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag)
-{
-  if (!ctx)
-    return 0;
-  switch (flag)
-    {
-    case ASSUAN_NO_WAITPID: return ctx->flags.no_waitpid;
-    case ASSUAN_CONFIDENTIAL: return ctx->confidential;
-    }
-  return 0;
-}
-
diff --git a/src/assuan.c b/src/assuan.c
new file mode 100644
index 0000000..d2c9f17
--- /dev/null
+++ b/src/assuan.c
@@ -0,0 +1,177 @@
+/* assuan.c - Global interface (not specific to context).
+   Copyright (C) 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 <stdlib.h>
+
+#include "assuan-defs.h"
+#include "debug.h"
+ 
+

+/* Global default state.  */
+
+/* The default error source gor generated error codes.  */
+static gpg_err_source_t _assuan_default_err_source = GPG_ERR_SOURCE_USER_1;
+
+/* The default memory management functions.  */
+static struct assuan_malloc_hooks _assuan_default_malloc_hooks =
+  { malloc, realloc, free };
+
+/* The default logging handler.  */
+static assuan_log_cb_t _assuan_default_log_cb = _assuan_log_handler;
+static void *_assuan_default_log_cb_data = NULL;
+
+

+/* Set the default gpg error source.  */
+void
+assuan_set_gpg_err_source (gpg_err_source_t errsource)
+{
+  _assuan_default_err_source = errsource;
+}
+
+
+/* Get the default gpg error source.  */
+gpg_err_source_t
+assuan_get_gpg_err_source (void)
+{
+  return _assuan_default_err_source;
+}
+
+

+/* Set the default malloc hooks.  */
+void
+assuan_set_malloc_hooks (assuan_malloc_hooks_t malloc_hooks)
+{
+  _assuan_default_malloc_hooks = *malloc_hooks;
+}
+
+
+/* Get the default malloc hooks.  */
+assuan_malloc_hooks_t
+assuan_get_malloc_hooks (void)
+{
+  return &_assuan_default_malloc_hooks;
+}
+
+

+/* Set the default log callback handler.  */
+void
+assuan_set_log_cb (assuan_log_cb_t log_cb, void *log_cb_data)
+{
+  _assuan_default_log_cb = log_cb;
+  _assuan_default_log_cb_data = log_cb_data;
+}
+
+
+/* Get the default log callback handler.  */
+void
+assuan_get_log_cb (assuan_log_cb_t *log_cb, void **log_cb_data)
+{
+  *log_cb = _assuan_default_log_cb;
+  *log_cb_data = _assuan_default_log_cb_data;
+}
+
+

+/* Create a new Assuan context.  The initial parameters are all needed
+   in the creation of the context.  */
+gpg_error_t
+assuan_new_ext (assuan_context_t *r_ctx, gpg_err_source_t err_source,
+		assuan_malloc_hooks_t malloc_hooks, assuan_log_cb_t log_cb,
+		void *log_cb_data)
+{
+  struct assuan_context_s wctx;
+  assuan_context_t ctx;
+
+  /* Set up a working context so we can use standard functions.  */
+  memset (&wctx, 0, sizeof (wctx));
+  wctx.err_source = err_source;
+  wctx.malloc_hooks = *malloc_hooks;
+  wctx.log_cb = log_cb;
+  wctx.log_cb_data = log_cb_data;
+
+  /* Need a new block for the trace macros to work.  */
+  {
+    TRACE_BEG8 (&wctx, ASSUAN_LOG_CTX, "assuan_new_ext", r_ctx,
+		"err_source = %i (%s), malloc_hooks = %p (%p, %p, %p), "
+		"log_cb = %p, log_cb_data = %p", err_source,
+		gpg_strsource (err_source), malloc_hooks, malloc_hooks->malloc,
+		malloc_hooks->realloc, malloc_hooks->free, log_cb, log_cb_data);
+
+    *r_ctx = NULL;
+    ctx = _assuan_malloc (&wctx, sizeof (*ctx));
+    if (!ctx)
+      return TRACE_ERR (gpg_err_code_from_syserror ());
+
+    memcpy (ctx, &wctx, sizeof (*ctx));
+
+    /* FIXME: Delegate to subsystems/engines, as the FDs are not our
+       responsibility (we don't deallocate them, for example).  */
+    ctx->input_fd = ASSUAN_INVALID_FD;
+    ctx->output_fd = ASSUAN_INVALID_FD;
+    ctx->inbound.fd = ASSUAN_INVALID_FD;
+    ctx->outbound.fd = ASSUAN_INVALID_FD;
+    ctx->listen_fd = ASSUAN_INVALID_FD;
+
+    *r_ctx = ctx;
+
+    return TRACE_SUC1 ("ctx=%p", ctx);
+  }
+}
+
+
+/* Create a new context with default arguments.  */
+gpg_error_t
+assuan_new (assuan_context_t *r_ctx)
+{
+  return assuan_new_ext (r_ctx, _assuan_default_err_source,
+			 &_assuan_default_malloc_hooks,
+			 _assuan_default_log_cb, 
+			 _assuan_default_log_cb_data);
+}
+
+
+/* Release all resources associated with an engine operation.  */
+void
+_assuan_reset (assuan_context_t ctx)
+{
+  if (ctx->engine.release)
+    {
+      (*ctx->engine.release) (ctx);
+      ctx->engine.release = NULL;
+    }
+
+  // FIXME: Clean standard commands
+}
+
+
+/* Release all resources associated with the given context.  */
+void
+assuan_release (assuan_context_t 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);
+}
diff --git a/src/assuan.h b/src/assuan.h
index 105862f..9e7db89 100644
--- a/src/assuan.h
+++ b/src/assuan.h
@@ -1,5 +1,5 @@
 /* assuan.h - Definitions for the Assuan IPC library
- * Copyright (C) 2001-2003, 2005, 2007-2009 Free Software Foundation, Inc.
+   Copyright (C) 2001-2003, 2005, 2007-2009 Free Software Foundation, Inc.
 
    This file is part of Assuan.
 
@@ -23,24 +23,21 @@
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include <stdarg.h>
+
 #ifndef _ASSUAN_NO_SOCKET_WRAPPER
 #ifdef _WIN32
 #include <ws2tcpip.h> 
 #else
 #include <sys/socket.h>
 #endif
-
-#include <gpg-error.h>
-
 #endif /*!_ASSUAN_NO_SOCKET_WRAPPER*/
 
-/* To use this file with libraries the following macros are useful:
+#include <gpg-error.h>
 
-     #define _ASSUAN_EXT_SYM_PREFIX _foo_
-   
-       This prefixes all external symbols with "_foo_".
+/* Compile time configuration:
 
-     #define _ASSUAN_NO_SOCKET_WRAPPER
+   #define _ASSUAN_NO_SOCKET_WRAPPER
 
        Do not include the definitions for the socket wrapper feature.
 
@@ -62,137 +59,6 @@
  */
 
 
-#ifdef _ASSUAN_EXT_SYM_PREFIX
-#define _ASSUAN_PREFIX1(x,y) x ## y
-#define _ASSUAN_PREFIX2(x,y) _ASSUAN_PREFIX1(x,y)
-#define _ASSUAN_PREFIX(x) _ASSUAN_PREFIX2(_ASSUAN_EXT_SYM_PREFIX,x)
-#define assuan_ _ASSUAN_PREFIX(assuan_)
-#define assuan_register_command _ASSUAN_PREFIX(assuan_register_command)
-#define assuan_register_post_cmd_notify \
-  _ASSUAN_PREFIX(assuan_register_post_cmd_notify)
-#define assuan_register_bye_notify _ASSUAN_PREFIX(assuan_register_bye_notify)
-#define assuan_register_reset_notify \
-  _ASSUAN_PREFIX(assuan_register_reset_notify)
-#define assuan_register_cancel_notify \
-  _ASSUAN_PREFIX(assuan_register_cancel_notify)
-#define assuan_register_input_notify \
-  _ASSUAN_PREFIX(assuan_register_input_notify)
-#define assuan_register_output_notify \
-  _ASSUAN_PREFIX(assuan_register_output_notify)
-#define assuan_register_option_handler \
-  _ASSUAN_PREFIX(assuan_register_option_handler)
-#define assuan_process _ASSUAN_PREFIX(assuan_process)
-#define assuan_process_next _ASSUAN_PREFIX(assuan_process_next)
-#define assuan_process_done _ASSUAN_PREFIX(assuan_process_done)
-#define assuan_get_active_fds _ASSUAN_PREFIX(assuan_get_active_fds)
-#define assuan_get_data_fp _ASSUAN_PREFIX(assuan_get_data_fp)
-#define assuan_set_okay_line _ASSUAN_PREFIX(assuan_set_okay_line)
-#define assuan_write_status _ASSUAN_PREFIX(assuan_write_status)
-#define assuan_command_parse_fd _ASSUAN_PREFIX(assuan_command_parse_fd)
-#define assuan_set_hello_line _ASSUAN_PREFIX(assuan_set_hello_line)
-#define assuan_accept _ASSUAN_PREFIX(assuan_accept)
-#define assuan_get_input_fd _ASSUAN_PREFIX(assuan_get_input_fd)
-#define assuan_get_output_fd _ASSUAN_PREFIX(assuan_get_output_fd)
-#define assuan_close_input_fd _ASSUAN_PREFIX(assuan_close_input_fd)
-#define assuan_close_output_fd _ASSUAN_PREFIX(assuan_close_output_fd)
-#define assuan_init_pipe_server _ASSUAN_PREFIX(assuan_init_pipe_server)
-#define assuan_deinit_server _ASSUAN_PREFIX(assuan_deinit_server)
-#define assuan_init_socket_server _ASSUAN_PREFIX(assuan_init_socket_server)
-#define assuan_init_socket_server_ext \
-  _ASSUAN_PREFIX(assuan_init_socket_server_ext)
-#define assuan_pipe_connect _ASSUAN_PREFIX(assuan_pipe_connect)
-#define assuan_pipe_connect_ext _ASSUAN_PREFIX(assuan_pipe_connect_ext)
-#define assuan_socket_connect _ASSUAN_PREFIX(assuan_socket_connect)
-#define assuan_socket_connect_ext _ASSUAN_PREFIX(assuan_socket_connect_ext)
-#define assuan_disconnect _ASSUAN_PREFIX(assuan_disconnect)
-#define assuan_get_pid _ASSUAN_PREFIX(assuan_get_pid)
-#define assuan_get_peercred _ASSUAN_PREFIX(assuan_get_peercred)
-#define assuan_transact _ASSUAN_PREFIX(assuan_transact)
-#define assuan_inquire _ASSUAN_PREFIX(assuan_inquire)
-#define assuan_inquire_ext _ASSUAN_PREFIX(assuan_inquire_ext)
-#define assuan_read_line _ASSUAN_PREFIX(assuan_read_line)
-#define assuan_pending_line _ASSUAN_PREFIX(assuan_pending_line)
-#define assuan_write_line _ASSUAN_PREFIX(assuan_write_line)
-#define assuan_send_data _ASSUAN_PREFIX(assuan_send_data)
-#define assuan_sendfd _ASSUAN_PREFIX(assuan_sendfd)
-#define assuan_receivefd _ASSUAN_PREFIX(assuan_receivefd)
-#define assuan_set_malloc_hooks _ASSUAN_PREFIX(assuan_set_malloc_hooks)
-#define assuan_set_io_hooks _ASSUAN_PREFIX(assuan_set_io_hooks)
-#define assuan_set_log_stream _ASSUAN_PREFIX(assuan_set_log_stream)
-#define assuan_set_error _ASSUAN_PREFIX(assuan_set_error)
-#define assuan_set_pointer _ASSUAN_PREFIX(assuan_set_pointer)
-#define assuan_get_pointer _ASSUAN_PREFIX(assuan_get_pointer)
-#define assuan_set_io_monitor _ASSUAN_PREFIX(assuan_set_io_monitor)
-#define assuan_begin_confidential _ASSUAN_PREFIX(assuan_begin_confidential)
-#define assuan_end_confidential _ASSUAN_PREFIX(assuan_end_confidential)
-#define assuan_set_assuan_err_source \
-  _ASSUAN_PREFIX(assuan_set_assuan_err_source)
-#define assuan_set_assuan_log_stream \
-  _ASSUAN_PREFIX(assuan_set_assuan_log_stream)
-#define assuan_get_assuan_log_stream \
-  _ASSUAN_PREFIX(assuan_get_assuan_log_stream)
-#define assuan_get_assuan_log_prefix \
-  _ASSUAN_PREFIX(assuan_get_assuan_log_prefix)
-#define assuan_set_flag _ASSUAN_PREFIX(assuan_set_flag)
-#define assuan_get_flag _ASSUAN_PREFIX(assuan_get_flag)
-#define assuan_set_assuan_log_prefix \
-  _ASSUAN_PREFIX(assuan_set_assuan_log_prefix)
-#define assuan_sock_close       _ASSUAN_PREFIX(assuan_sock_close)      
-#define assuan_sock_new         _ASSUAN_PREFIX(assuan_sock_new)        
-#define assuan_sock_connect     _ASSUAN_PREFIX(assuan_sock_connect)    
-#define assuan_sock_bind        _ASSUAN_PREFIX(assuan_sock_bind)       
-#define assuan_sock_get_nonce   _ASSUAN_PREFIX(assuan_sock_get_nonce)
-#define assuan_sock_check_nonce _ASSUAN_PREFIX(assuan_sock_check_nonce)
-
-
-/* And now the internal functions, argh...  */
-#define _assuan_read_line _ASSUAN_PREFIX(_assuan_read_line)
-#define _assuan_cookie_write_data _ASSUAN_PREFIX(_assuan_cookie_write_data)
-#define _assuan_cookie_write_flush _ASSUAN_PREFIX(_assuan_cookie_write_flush)
-#define _assuan_read_from_server _ASSUAN_PREFIX(_assuan_read_from_server)
-#define _assuan_domain_init _ASSUAN_PREFIX(_assuan_domain_init)
-#define _assuan_register_std_commands \
-  _ASSUAN_PREFIX(_assuan_register_std_commands)
-#define _assuan_simple_read _ASSUAN_PREFIX(_assuan_simple_read)
-#define _assuan_simple_write _ASSUAN_PREFIX(_assuan_simple_write)
-#define _assuan_io_read _ASSUAN_PREFIX(_assuan_io_read)
-#define _assuan_io_write _ASSUAN_PREFIX(_assuan_io_write)
-#define _assuan_io_hooks _ASSUAN_PREFIX(_assuan_io_hooks)
-#define _assuan_new_context _ASSUAN_PREFIX(_assuan_new_context)
-#define _assuan_release_context _ASSUAN_PREFIX(_assuan_release_context)
-#define _assuan_malloc _ASSUAN_PREFIX(_assuan_malloc)
-#define _assuan_realloc _ASSUAN_PREFIX(_assuan_realloc)
-#define _assuan_calloc _ASSUAN_PREFIX(_assuan_calloc)
-#define _assuan_free _ASSUAN_PREFIX(_assuan_free)
-#define _assuan_log_print_buffer _ASSUAN_PREFIX(_assuan_log_print_buffer)
-#define _assuan_log_sanitized_string \
-  _ASSUAN_PREFIX(_assuan_log_sanitized_string)
-#define _assuan_log_printf _ASSUAN_PREFIX(_assuan_log_printf)
-#define _assuan_set_default_log_stream \
-  _ASSUAN_PREFIX(_assuan_set_default_log_stream)
-#define _assuan_w32_strerror _ASSUAN_PREFIX(_assuan_w32_strerror)
-#define _assuan_gpg_strerror_r _ASSUAN_PREFIX(_assuan_gpg_strerror_r)
-#define _assuan_gpg_strsource  _ASSUAN_PREFIX(_assuan_gpg_strsource)
-#define _assuan_write_line _ASSUAN_PREFIX(_assuan_write_line)
-#define _assuan_error _ASSUAN_PREFIX(_assuan_error)
-#define _assuan_error_is_eagain   _ASSUAN_PREFIX(_assuan_error_is_eagain)
-#define _assuan_init_uds_io _ASSUAN_PREFIX(_assuan_init_uds_io)
-#define _assuan_uds_close_fds _ASSUAN_PREFIX(_assuan_uds_close_fds)
-#define _assuan_uds_deinit _ASSUAN_PREFIX(_assuan_uds_deinit)
-#define _assuan_simple_recvmsg _ASSUAN_PREFIX(_assuan_simple_recvmsg)
-#define _assuan_simple_sendmsg _ASSUAN_PREFIX(_assuan_simple_sendmsg)
-#define _assuan_waitpid _ASSUAN_PREFIX(_assuan_waitpid)
-#define _assuan_sock_wsa2errno   _ASSUAN_PREFIX(_assuan_sock_wsa2errno)
-#define _assuan_sock_close       _ASSUAN_PREFIX(_assuan_sock_close)      
-#define _assuan_sock_new         _ASSUAN_PREFIX(_assuan_sock_new)        
-#define _assuan_sock_connect     _ASSUAN_PREFIX(_assuan_sock_connect)    
-#define _assuan_sock_bind        _ASSUAN_PREFIX(_assuan_sock_bind)       
-#define _assuan_sock_get_nonce   _ASSUAN_PREFIX(_assuan_sock_get_nonce)
-#define _assuan_sock_check_nonce _ASSUAN_PREFIX(_assuan_sock_check_nonce)
-
-#endif /*_ASSUAN_EXT_SYM_PREFIX*/
-
-
 #ifdef __cplusplus
 extern "C"
 {
@@ -217,20 +83,6 @@ extern "C"
 #endif
 
 
-/* Definitions of flags for assuan_set_flag().  */
-typedef unsigned int assuan_flag_t;
-
-/* When using a pipe server, by default Assuan will wait for the
-   forked process to die in assuan_disconnect.  In certain cases this
-   is not desirable.  By setting this flag, the waitpid will be
-   skipped and the caller is responsible to cleanup a forked
-   process. */
-#define ASSUAN_NO_WAITPID 1
-/* This flag indicates whether Assuan logging is in confidential
-   mode. Use assuan_{begin,end}_condidential to change the mode.  */
-#define ASSUAN_CONFIDENTIAL 2
-
-
 #define ASSUAN_LINELENGTH 1002 /* 1000 + [CR,]LF */
 
 struct assuan_context_s;
@@ -279,19 +131,146 @@ struct sockaddr_un
 };
 #endif
 
+

+/* Global interface.  */
 
-/* Definition of hook functions used to conditionally replace the
-   default I/O functions. */
-struct assuan_io_hooks
+struct assuan_malloc_hooks
 {
-  int (*read_hook)(assuan_context_t, assuan_fd_t, void *, size_t, ssize_t *);
-  int (*write_hook)(assuan_context_t, assuan_fd_t fd,
-                    const void *, size_t, ssize_t *);
+  void *(*malloc) (size_t cnt);
+  void *(*realloc) (void *ptr, size_t cnt);
+  void (*free) (void *ptr);
 };
-typedef struct assuan_io_hooks *assuan_io_hooks_t;
+typedef struct assuan_malloc_hooks *assuan_malloc_hooks_t;
+
+/* Categories for log messages.  */
+#define ASSUAN_LOG_INIT 1
+#define ASSUAN_LOG_CTX 2
+#define ASSUAN_LOG_ENGINE 3
+#define ASSUAN_LOG_DATA 4
+#define ASSUAN_LOG_SYSIO 5
+
+/* If MSG is NULL, return true/false depending on if this category is
+   logged.  This is used to probe before expensive log message
+   generation (buffer dumps).  */
+typedef int (*assuan_log_cb_t) (assuan_context_t ctx, void *hook,
+				unsigned int cat, const char *msg);
+
+/* Set the default gpg error source.  */
+void assuan_set_gpg_err_source (gpg_err_source_t errsource);
+
+/* Get the default gpg error source.  */
+gpg_err_source_t assuan_get_gpg_err_source (void);
+
+
+/* Set the default malloc hooks.  */
+void assuan_set_malloc_hooks (assuan_malloc_hooks_t malloc_hooks);
+
+/* Get the default malloc hooks.  */
+assuan_malloc_hooks_t assuan_get_malloc_hooks (void);
+
+
+/* Set the default log callback handler.  */
+void assuan_set_log_cb (assuan_log_cb_t log_cb, void *log_cb_data);
+
+/* Get the default log callback handler.  */
+void assuan_get_log_cb (assuan_log_cb_t *log_cb, void **log_cb_data);
+
+
+/* Create a new Assuan context.  The initial parameters are all needed
+   in the creation of the context.  */
+gpg_error_t assuan_new_ext (assuan_context_t *ctx, gpg_err_source_t errsource,
+			    assuan_malloc_hooks_t malloc_hooks,
+			    assuan_log_cb_t log_cb, void *log_cb_data);
+
+/* Create a new context with default arguments.  */
+gpg_error_t assuan_new (assuan_context_t *ctx);
+
+/* Release all resources associated with the given context.  */
+void assuan_release (assuan_context_t ctx);
 
+

+/* Set user-data in a context.  */
+void assuan_set_pointer (assuan_context_t ctx, void *pointer);
+
+/* Get user-data in a context.  */
+void *assuan_get_pointer (assuan_context_t ctx);
+
+
+/* Definitions of flags for assuan_set_flag().  */
+typedef unsigned int assuan_flag_t;
+
+/* When using a pipe server, by default Assuan will wait for the
+   forked process to die in assuan_release.  In certain cases this
+   is not desirable.  By setting this flag, the waitpid will be
+   skipped and the caller is responsible to cleanup a forked
+   process. */
+#define ASSUAN_NO_WAITPID 1
+/* 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
+
+/* 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;
+   see the description of the type assuan_flag_t for details.  */
+void assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value);
+
+/* Return the VALUE of FLAG in context CTX.  */
+int assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag);
+
+
+/* Same as assuan_set_flag (ctx, ASSUAN_NO_WAITPID, 1).  */
+void assuan_begin_confidential (assuan_context_t ctx);
+
+/* Same as assuan_set_flag (ctx, ASSUAN_NO_WAITPID, 0).  */
+void assuan_end_confidential (assuan_context_t ctx);
+
+
+/* Direction values for assuan_set_io_monitor.  */
+#define ASSUAN_IO_FROM_PEER 0
+#define ASSUAN_IO_TO_PEER 1
+
+/* Return flags of I/O monitor.  */
+#define ASSUAN_IO_MONITOR_NOLOG 1
+#define ASSUAN_IO_MONITOR_IGNORE 2
+
+/* The IO monitor gets to see all I/O on the context, and can return
+   ASSUAN_IO_MONITOR_* bits to control actions on it.  */
+typedef unsigned int (*assuan_io_monitor_t) (assuan_context_t ctx, void *hook,
+					     int inout, const char *line,
+					     size_t linelen);
+
+/* Set the IO monitor function.  */
+void assuan_set_io_monitor (assuan_context_t ctx,
+			    assuan_io_monitor_t io_monitor, void *hook_data);
 
+

+/* Configuration of the default log handler.  */
 
+/* Set the stream to which assuan should log message not associated
+   with a context.  By default, this is stderr.  The default value
+   will be changed when the first log stream is associated with a
+   context.  Note, that this function is not thread-safe and should
+   in general be used right at startup. */
+extern void assuan_set_assuan_log_stream (FILE *fp);
+
+/* Return the stream which is currently being using for global logging.  */
+extern FILE *assuan_get_assuan_log_stream (void);
+
+/* Set the prefix to be used at the start of a line emitted by assuan
+   on the log stream.  The default is the empty string.  Note, that
+   this function is not thread-safe and should in general be used
+   right at startup. */
+void assuan_set_assuan_log_prefix (const char *text);
+
+/* Return a prefix to be used at the start of a line emitted by assuan
+   on the log stream.  The default implementation returns the empty
+   string, i.e. ""  */
+const char *assuan_get_assuan_log_prefix (void);
+
+/* Set the per context log stream for the default log handler.  */
+void assuan_set_log_stream (assuan_context_t ctx, FILE *fp);
+
+

 /*-- assuan-handler.c --*/
 gpg_error_t assuan_register_command (assuan_context_t ctx,
 				     const char *cmd_string,
@@ -344,41 +323,40 @@ gpg_error_t assuan_close_output_fd (assuan_context_t ctx);
 
 
 /*-- assuan-pipe-server.c --*/
-gpg_error_t assuan_init_pipe_server (assuan_context_t *r_ctx, int filedes[2]);
-void assuan_deinit_server (assuan_context_t ctx);
+gpg_error_t assuan_init_pipe_server (assuan_context_t ctx, int filedes[2]);
 
 /*-- assuan-socket-server.c --*/
-gpg_error_t assuan_init_socket_server (assuan_context_t *r_ctx,
+gpg_error_t assuan_init_socket_server (assuan_context_t ctx,
 				       assuan_fd_t listen_fd);
-gpg_error_t assuan_init_socket_server_ext (assuan_context_t *r_ctx,
+gpg_error_t assuan_init_socket_server_ext (assuan_context_t ctx,
 					   assuan_fd_t fd,
 					   unsigned int flags);
 void assuan_set_sock_nonce (assuan_context_t ctx, assuan_sock_nonce_t *nonce);
 
 /*-- assuan-pipe-connect.c --*/
-gpg_error_t assuan_pipe_connect (assuan_context_t *ctx,
+gpg_error_t assuan_pipe_connect (assuan_context_t ctx,
 				 const char *name,
-				 const char *const argv[],
+				 const char *argv[],
 				 int *fd_child_list);
-gpg_error_t assuan_pipe_connect_ext (assuan_context_t *ctx, 
+gpg_error_t assuan_pipe_connect_ext (assuan_context_t ctx,
 				     const char *name,
-				     const char *const argv[],
+				     const char *argv[],
 				     int *fd_child_list,
 				     void (*atfork) (void *, int),
 				     void *atforkvalue,
 				     unsigned int flags);
 
 /*-- assuan-socket-connect.c --*/
-gpg_error_t assuan_socket_connect (assuan_context_t *ctx, 
+gpg_error_t assuan_socket_connect (assuan_context_t ctx, 
 				   const char *name,
 				   pid_t server_pid);
-gpg_error_t assuan_socket_connect_ext (assuan_context_t *ctx,
+
+gpg_error_t assuan_socket_connect_ext (assuan_context_t ctx,
 				       const char *name,
 				       pid_t server_pid,
 				       unsigned int flags);
 
 /*-- assuan-connect.c --*/
-void assuan_disconnect (assuan_context_t ctx);
 pid_t assuan_get_pid (assuan_context_t ctx);
 #ifndef _WIN32
 gpg_error_t assuan_get_peercred (assuan_context_t ctx,
@@ -424,63 +402,8 @@ gpg_error_t assuan_receivefd (assuan_context_t ctx, assuan_fd_t *fd);
 
 
 /*-- assuan-util.c --*/
-void assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
-                               void *(*new_realloc_func)(void *p, size_t n),
-                               void (*new_free_func)(void*) );
-void assuan_set_io_hooks (assuan_io_hooks_t io_hooks);
-void assuan_set_log_stream (assuan_context_t ctx, FILE *fp);
 gpg_error_t assuan_set_error (assuan_context_t ctx, gpg_error_t err, const char *text);
-void assuan_set_pointer (assuan_context_t ctx, void *pointer);
-void *assuan_get_pointer (assuan_context_t ctx);
-
-void assuan_begin_confidential (assuan_context_t ctx);
-void assuan_end_confidential (assuan_context_t ctx);
-
-void assuan_set_io_monitor (assuan_context_t ctx,
-                            unsigned int (*monitor)(assuan_context_t ctx,
-                                                    int direction,
-                                                    const char *line,
-                                                    size_t linelen));
-
-/* 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;
-   see the description of the type assuan_flag_t for details. */
-void assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value);
-
-/* Return the VALUE of FLAG in context CTX. */ 
-int assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag);
-
 
-/*-- assuan-errors.c --*/
-
-/* Enable gpg-error style error codes.  ERRSOURCE is one of gpg-error
-   sources.  Note, that this function is not thread-safe and should be
-   used right at startup. Switching back to the old style mode is not
-   supported. */
-void assuan_set_assuan_err_source (gpg_err_source_t errsource);
-
-/*-- assuan-logging.c --*/
-
-/* Set the stream to which assuan should log message not associated
-   with a context.  By default, this is stderr.  The default value
-   will be changed when the first log stream is associated with a
-   context.  Note, that this function is not thread-safe and should
-   in general be used right at startup. */
-extern void assuan_set_assuan_log_stream (FILE *fp);
-
-/* Return the stream which is currently being using for global logging.  */
-extern FILE *assuan_get_assuan_log_stream (void);
-
-/* Set the prefix to be used at the start of a line emitted by assuan
-   on the log stream.  The default is the empty string.  Note, that
-   this function is not thread-safe and should in general be used
-   right at startup. */
-void assuan_set_assuan_log_prefix (const char *text);
-
-/* Return a prefix to be used at the start of a line emitted by assuan
-   on the log stream.  The default implementation returns the empty
-   string, i.e. ""  */
-const char *assuan_get_assuan_log_prefix (void);
 
 
 /*-- assuan-socket.c --*/
diff --git a/src/context.c b/src/context.c
new file mode 100644
index 0000000..d87672b
--- /dev/null
+++ b/src/context.c
@@ -0,0 +1,127 @@
+/* context.c - Context specific interface.
+   Copyright (C) 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 "assuan-defs.h"
+#include "debug.h"
+
+

+/* Set user-data in a context.  */
+void
+assuan_set_pointer (assuan_context_t ctx, void *pointer)
+{
+  if (ctx)
+    ctx->user_pointer = pointer;
+}
+
+
+/* Get user-data in a context.  */
+void *
+assuan_get_pointer (assuan_context_t ctx)
+{
+  if (! ctx)
+    return NULL;
+
+  return ctx->user_pointer;
+}
+
+

+/* 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;
+   see the description of the type assuan_flag_t for details.  */
+void
+assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value)
+{
+  if (!ctx)
+    return;
+
+  switch (flag)
+    {
+    case ASSUAN_NO_WAITPID:
+      ctx->flags.no_waitpid = value;
+      break;
+
+    case ASSUAN_CONFIDENTIAL:
+      ctx->flags.confidential = value;
+      break;
+    }
+}
+
+
+/* Return the VALUE of FLAG in context CTX.  */
+int
+assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag)
+{
+  if (! ctx)
+    return 0;
+
+  switch (flag)
+    {
+    case ASSUAN_NO_WAITPID:
+      return ctx->flags.no_waitpid;
+    case ASSUAN_CONFIDENTIAL:
+      return ctx->flags.confidential;
+    }
+
+  return 0;
+}
+
+
+/* Same as assuan_set_flag (ctx, ASSUAN_NO_WAITPID, 1).  */
+void
+assuan_begin_confidential (assuan_context_t ctx)
+{
+  assuan_set_flag (ctx, ASSUAN_CONFIDENTIAL, 1);
+}
+
+
+/* Same as assuan_set_flag (ctx, ASSUAN_NO_WAITPID, 0).  */
+void
+assuan_end_confidential (assuan_context_t ctx)
+{
+  assuan_set_flag (ctx, ASSUAN_CONFIDENTIAL, 0);
+}
+
+

+/* 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;
+    }
+}
+
+

+/* Store the error in the context so that the error sending function
+  can take out a descriptive text.  Inside the assuan code, use the
+  macro set_error instead of this function. */
+gpg_error_t
+assuan_set_error (assuan_context_t ctx, gpg_error_t err, const char *text)
+{
+  ctx->err_no = err;
+  ctx->err_str = text;
+  return err;
+}
diff --git a/src/conversion.c b/src/conversion.c
new file mode 100644
index 0000000..af5026e
--- /dev/null
+++ b/src/conversion.c
@@ -0,0 +1,116 @@
+/* conversion.c - String conversion helper functions.
+   Copyright (C) 2000 Werner Koch (dd9jn)
+   Copyright (C) 2001, 2002, 2003, 2004, 2007 g10 Code GmbH
+ 
+   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, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#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>
+
+#include "assuan-defs.h"
+#include "debug.h"
+
+

+/* Convert the number NR to a hexadecimal string.  Returns the tail
+   pointer.  */
+static char *
+_assuan_bytetohex (int nr, char *str)
+{
+  static char hexdigits[] = "0123456789abcdef";
+  int i;
+
+#define NROFHEXDIGITS 2
+  for (i = 0; i < NROFHEXDIGITS; i++)
+    {
+      int digit = (nr >> (i << 2)) & 0xf;
+      *(str++) = hexdigits[digit];
+    }
+  return str;
+}
+
+
+/* Encode the C formatted string SRC and return the malloc'ed result.  */
+char *
+_assuan_encode_c_string (assuan_context_t ctx, const char *src)
+{
+  const unsigned char *istr;
+  char *res;
+  char *ostr;
+  
+  ostr = _assuan_malloc (ctx, 4 * strlen (src) + 1);
+  if (! *ostr)
+    return NULL;
+
+  res = ostr;
+
+  for (istr = (const unsigned char *) src; *istr; istr++)
+    {
+      int c = 0;
+
+      switch (*istr)
+	{
+	case '\r':
+	  c = 'r';
+	  break;
+
+	case '\n':
+	  c = 'n';
+	  break;
+
+	case '\f':
+	  c = 'f';
+	  break;
+
+	case '\v':
+	  c = 'v';
+	  break;
+
+	case '\b':
+	  c = 'b';
+	  break;
+
+	default:
+	  if ((isascii (*istr) && isprint (*istr)) || (*istr >= 0x80))
+	    *(ostr++) = *istr;
+	  else
+	    {
+	      *(ostr++) = '\\';
+	      *(ostr++) = 'x';
+	      ostr = _assuan_bytetohex (*istr, ostr);
+	    }
+	}
+
+      if (c)
+	{
+	  *(ostr++) = '\\';
+	  *(ostr++) = c;
+	}
+    }
+  *(ostr) = '\0';
+
+  return res;
+}
diff --git a/src/debug.c b/src/debug.c
new file mode 100644
index 0000000..1a0df7e
--- /dev/null
+++ b/src/debug.c
@@ -0,0 +1,179 @@
+/* debug.c - helpful output in desperate situations
+   Copyright (C) 2000 Werner Koch (dd9jn)
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2009 g10 Code GmbH
+ 
+   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, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+   MA 02110-1301, USA.  */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#ifndef HAVE_DOSISH_SYSTEM
+#  include <sys/types.h>
+#  include <sys/stat.h>
+#  include <fcntl.h>
+#endif
+#include <assert.h>
+
+#include "assuan-defs.h"
+#include "debug.h"
+
+

+/* Log the formatted string FORMAT at debug category CAT or higher.  */
+void
+_assuan_debug (assuan_context_t ctx, unsigned int cat, const char *format, ...)
+{
+  va_list arg_ptr;
+  int saved_errno;
+  char *msg;
+  int res;
+
+  if (ctx->log_cb == NULL)
+    return;
+
+  saved_errno = errno;
+  va_start (arg_ptr, format);
+  res = vasprintf (&msg, format, arg_ptr);
+  va_end (arg_ptr);
+  if (res < 0)
+    return;
+  ctx->log_cb (ctx, ctx->log_cb_data, cat, msg);
+  errno = saved_errno;
+}
+
+
+/* Start a new debug line in *LINE, logged at level LEVEL or higher,
+   and starting with the formatted string FORMAT.  */
+void
+_assuan_debug_begin (assuan_context_t ctx,
+		     void **line, unsigned int cat, const char *format, ...)
+{
+  va_list arg_ptr;
+  int res;
+
+  *line = NULL;
+  /* Probe if this wants to be logged based on category.  */
+  if (! ctx->log_cb ||
+      ! (*ctx->log_cb) (ctx, ctx->log_cb_data, cat, NULL))
+    return;
+  
+  va_start (arg_ptr, format);
+  res = vasprintf ((char **) line, format, arg_ptr);
+  va_end (arg_ptr);
+  if (res < 0)
+    *line = NULL;
+}
+
+
+/* Add the formatted string FORMAT to the debug line *LINE.  */
+void
+_assuan_debug_add (assuan_context_t ctx, void **line, const char *format, ...)
+{
+  va_list arg_ptr;
+  char *toadd;
+  char *result;
+  int res;
+
+  if (!*line)
+    return;
+
+  va_start (arg_ptr, format);
+  res = vasprintf (&toadd, format, arg_ptr);
+  va_end (arg_ptr);
+  if (res < 0)
+    {
+      free (*line);
+      *line = NULL;
+    }
+  res = asprintf (&result, "%s%s", *(char **) line, toadd);
+  free (toadd);
+  free (*line);
+  if (res < 0)
+    *line = NULL;
+  else
+    *line = result;
+}
+
+
+/* Finish construction of *LINE and send it to the debug output
+   stream.  */
+void
+_assuan_debug_end (assuan_context_t ctx, void **line, unsigned int cat)
+{
+  if (!*line)
+    return;
+
+  /* Force logging here by using category ~0.  */
+  _assuan_debug (ctx, ~0, "%s", *line);
+  free (*line);
+  *line = NULL;
+}
+
+
+#define TOHEX(val) (((val) < 10) ? ((val) + '0') : ((val) - 10 + 'a'))
+
+void
+_assuan_debug_buffer (assuan_context_t ctx, unsigned int cat,
+		      const char *const fmt, const char *const func,
+		      const char *const tagname, void *tag,
+		      const char *const buffer, size_t len)
+{
+  int idx = 0;
+  int j;
+
+  /* Probe if this wants to be logged based on category.  */
+  if (! ctx->log_cb ||
+      ! (*ctx->log_cb) (ctx, ctx->log_cb_data, cat, NULL))
+    return;
+
+  while (idx < len)
+    {
+      char str[51];
+      char *strp = str;
+      char *strp2 = &str[34];
+      
+      for (j = 0; j < 16; j++)
+	{
+	  unsigned char val;
+	  if (idx < len)
+	    {
+	      val = buffer[idx++];
+	      *(strp++) = TOHEX (val >> 4);
+	      *(strp++) = TOHEX (val % 16);
+	      *(strp2++) = isprint (val) ? val : '.';
+	    }
+	  else
+	    {
+	      *(strp++) = ' ';
+	      *(strp++) = ' ';
+	    }
+	  if (j == 7)
+	    *(strp++) = ' ';
+	}
+      *(strp++) = ' ';
+      *(strp2) = '\0';
+
+      _assuan_debug (ctx, cat, fmt, func, tagname, tag, str);
+    }
+}
diff --git a/src/debug.h b/src/debug.h
new file mode 100644
index 0000000..13e5419
--- /dev/null
+++ b/src/debug.h
@@ -0,0 +1,260 @@
+/* debug.h - interface to debugging functions
+   Copyright (C) 2002, 2004, 2005, 2007 g10 Code GmbH
+ 
+   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, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+#include <string.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#include "assuan-defs.h"
+
+/* Indirect stringification, requires __STDC__ to work.  */
+#define STRINGIFY(v) #v
+#define XSTRINGIFY(v) STRINGIFY(v)
+
+
+

+/* Remove path components from filenames (i.e. __FILE__) for cleaner
+   logs. */
+static inline const char *_assuan_debug_srcname (const char *file)
+  ASSUAN_GCC_A_PURE;
+
+static inline const char *
+_assuan_debug_srcname (const char *file)
+{
+  const char *s = strrchr (file, '/');
+  return s ? s + 1 : file;
+}
+
+
+/* Called early to initialize the logging.  */
+void _assuan_debug_subsystem_init (void);
+
+/* Log the formatted string FORMAT at debug level LEVEL or higher.  */
+void _assuan_debug (assuan_context_t ctx, unsigned int cat,
+		    const char *format, ...);
+
+/* Start a new debug line in *LINE, logged at level LEVEL or higher,
+   and starting with the formatted string FORMAT.  */
+void _assuan_debug_begin (assuan_context_t ctx,
+			  void **helper, unsigned int cat,
+			  const char *format, ...);
+
+/* Add the formatted string FORMAT to the debug line *LINE.  */
+void _assuan_debug_add (assuan_context_t ctx,
+			void **helper, const char *format, ...);
+
+/* Finish construction of *LINE and send it to the debug output
+   stream.  */
+void _assuan_debug_end (assuan_context_t ctx,
+			void **helper, unsigned int cat);
+
+void _assuan_debug_buffer (assuan_context_t ctx, unsigned int cat,
+			   const char *const fmt,
+			   const char *const func, const char *const tagname,
+			   void *tag, const char *const buffer, size_t len);
+
+

+/* Trace support.  */
+
+#define _TRACE(ctx, lvl, name, tag)					\
+  assuan_context_t _assuan_trace_context = ctx;				\
+  int _assuan_trace_level = lvl;					\
+  const char *const _assuan_trace_func = name;				\
+  const char *const _assuan_trace_tagname = STRINGIFY (tag);		\
+  void *_assuan_trace_tag = (void *) (uintptr_t) tag
+
+#define TRACE_BEG(ctx,lvl, name, tag)			     \
+  _TRACE (ctx, lvl, name, tag);				     \
+  _assuan_debug (_assuan_trace_context, _assuan_trace_level, \
+		 "%s (%s=%p): enter\n",			     \
+		_assuan_trace_func, _assuan_trace_tagname,   \
+		_assuan_trace_tag), 0
+#define TRACE_BEG0(ctx, lvl, name, tag, fmt)				\
+  _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), 0
+#define TRACE_BEG1(ctx, lvl, name, tag, fmt, arg1)			\
+  _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), 0
+#define TRACE_BEG2(ctx, lvl, name, tag, fmt, arg1, arg2)		\
+  _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), 0
+#define TRACE_BEG3(ctx, lvl, name, tag, fmt, arg1, arg2, arg3)	      \
+  _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), 0
+#define TRACE_BEG4(ctx, lvl, name, tag, fmt, arg1, arg2, arg3, arg4)	\
+  _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), 0
+
+#define TRACE_BEG8(ctx, lvl, name, tag, fmt, arg1, arg2, arg3, arg4,	\
+		   arg5, arg6, arg7, arg8)				\
+  _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, arg7, arg8), 0
+
+#define TRACE(ctx, lvl, name, tag)					\
+  _assuan_debug (ctx, lvl, "%s (%s=%p): call\n",			\
+		 name, STRINGIFY (tag), (void *) (uintptr_t) tag), 0
+#define TRACE0(ctx, lvl, name, tag, fmt)				\
+  _assuan_debug (ctx, lvl, "%s (%s=%p): call: " fmt "\n",		\
+		 name, STRINGIFY (tag), (void *) (uintptr_t) tag), 0
+#define TRACE1(ctx, lvl, name, tag, fmt, arg1)				\
+  _assuan_debug (ctx, lvl, "%s (%s=%p): call: " fmt "\n",		\
+		 name, STRINGIFY (tag), (void *) (uintptr_t) tag, arg1), 0
+#define TRACE2(ctx, lvl, name, tag, fmt, arg1, arg2)			\
+  _assuan_debug (ctx, lvl, "%s (%s=%p): call: " fmt "\n",		\
+		 name, STRINGIFY (tag), (void *) (uintptr_t) tag, arg1, \
+		 arg2), 0
+#define TRACE3(ctx, lvl, name, tag, fmt, arg1, arg2, arg3)		\
+  _assuan_debug (ctx, lvl, "%s (%s=%p): call: " fmt "\n",		\
+		 name, STRINGIFY (tag), (void *) (uintptr_t) tag, arg1, \
+		 arg2, arg3), 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,	\
+		 arg2, arg3, arg4, arg5, arg6), 0
+
+#define TRACE_ERR(err)							\
+  err == 0 ? (TRACE_SUC ()) :						\
+    (_assuan_debug (_assuan_trace_context, _assuan_trace_level,		\
+		    "%s (%s=%p): error: %s <%s>\n",			\
+		    _assuan_trace_func, _assuan_trace_tagname,		\
+		    _assuan_trace_tag, gpg_strerror (err),		\
+		    gpg_strsource (ctx->err_source)),			\
+     _assuan_error (ctx, err))
+
+/* The cast to void suppresses GCC warnings.  */
+#define TRACE_SYSRES(res)						\
+  res >= 0 ? ((void) (TRACE_SUC1 ("result=%i", res)), (res)) :		\
+    (_assuan_debug (_assuan_trace_context, _assuan_trace_level, "%s (%s=%p): error: %s\n", \
+		    _assuan_trace_func, _assuan_trace_tagname,		\
+		   _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_trace_func, _assuan_trace_tagname,		\
+		    _assuan_trace_tag, strerror (res)), (res))
+
+#define TRACE_SUC()						 \
+  _assuan_debug (_assuan_trace_context, _assuan_trace_level,	 \
+		 "%s (%s=%p): leave\n",				 \
+		_assuan_trace_func, _assuan_trace_tagname,	 \
+		_assuan_trace_tag), 0
+#define TRACE_SUC0(fmt)							\
+  _assuan_debug (_assuan_trace_context, _assuan_trace_level,		\
+		 "%s (%s=%p): leave: " fmt "\n",			\
+		 _assuan_trace_func, _assuan_trace_tagname,		\
+		 _assuan_trace_tag), 0
+#define TRACE_SUC1(fmt, arg1)						\
+  _assuan_debug (_assuan_trace_context, _assuan_trace_level,		\
+		 "%s (%s=%p): leave: " fmt "\n",			\
+		 _assuan_trace_func, _assuan_trace_tagname,		\
+		 _assuan_trace_tag, arg1), 0
+#define TRACE_SUC2(fmt, arg1, arg2)					\
+  _assuan_debug (_assuan_trace_context, _assuan_trace_level,		\
+		 "%s (%s=%p): leave: " fmt "\n",			\
+		 _assuan_trace_func, _assuan_trace_tagname,		\
+		 _assuan_trace_tag, arg1, arg2), 0
+#define TRACE_SUC5(fmt, arg1, arg2, arg3, arg4, arg5)			\
+  _assuan_debug (_assuan_trace_context, _assuan_trace_level,		\
+		 "%s (%s=%p): leave: " fmt "\n",			\
+		 _assuan_trace_func, _assuan_trace_tagname,		\
+		 _assuan_trace_tag, arg1, arg2, arg3, arg4, arg5), 0
+
+#define TRACE_LOG(fmt)							\
+  _assuan_debug (_assuan_trace_context, _assuan_trace_level,		\
+		 "%s (%s=%p): check: " fmt "\n",			\
+		 _assuan_trace_func, _assuan_trace_tagname,		\
+		 _assuan_trace_tag), 0
+#define TRACE_LOG1(fmt, arg1)						\
+  _assuan_debug (_assuan_trace_context, _assuan_trace_level,		\
+		 "%s (%s=%p): check: " fmt "\n",			\
+		_assuan_trace_func, _assuan_trace_tagname,		\
+		_assuan_trace_tag, arg1), 0
+#define TRACE_LOG2(fmt, arg1, arg2)				    \
+  _assuan_debug (_assuan_trace_context, _assuan_trace_level,	    \
+		 "%s (%s=%p): check: " fmt "\n",		    \
+		 _assuan_trace_func, _assuan_trace_tagname,	    \
+		 _assuan_trace_tag, arg1, arg2), 0
+#define TRACE_LOG3(fmt, arg1, arg2, arg3)			    \
+  _assuan_debug (_assuan_trace_context, _assuan_trace_level,	    \
+		 "%s (%s=%p): check: " fmt "\n",		    \
+		 _assuan_trace_func, _assuan_trace_tagname,	    \
+		 _assuan_trace_tag, arg1, arg2, arg3), 0
+#define TRACE_LOG4(fmt, arg1, arg2, arg3, arg4)			    \
+  _assuan_debug (_assuan_trace_context, _assuan_trace_level,	    \
+		 "%s (%s=%p): check: " fmt "\n",		    \
+		_assuan_trace_func, _assuan_trace_tagname,	    \
+		_assuan_trace_tag, arg1, arg2, arg3, arg4), 0
+#define TRACE_LOG6(fmt, arg1, arg2, arg3, arg4, arg5, arg6)	    \
+  _assuan_debug (_assuan_trace_context, _assuan_trace_level,	    \
+		 "%s (%s=%p): check: " fmt "\n",			\
+		 _assuan_trace_func, _assuan_trace_tagname,		\
+		 _assuan_trace_tag, arg1, arg2, arg3, arg4, arg5,	\
+		 arg6), 0
+
+#define TRACE_LOGBUF(buf, len)						\
+  _assuan_debug_buffer (_assuan_trace_context, _assuan_trace_level,	\
+			"%s (%s=%p): check: %s",			\
+			_assuan_trace_func, _assuan_trace_tagname,	\
+			_assuan_trace_tag, buf, len)
+
+#define TRACE_SEQ(hlp,fmt)						\
+  _assuan_debug_begin (_assuan_trace_context, &(hlp),			\
+		       "%s (%s=%p): check: " fmt,			\
+		       _assuan_trace_func, _assuan_trace_tagname,	\
+		       _assuan_trace_tag)
+#define TRACE_ADD0(hlp,fmt) \
+  _assuan_debug_add (_assuan_trace_context, &(hlp), fmt)
+#define TRACE_ADD1(hlp,fmt,a) \
+  _assuan_debug_add (_assuan_trace_context, &(hlp), fmt, (a))
+#define TRACE_ADD2(hlp,fmt,a,b) \
+  _assuan_debug_add (_assuan_trace_context, &(hlp), fmt, (a), (b))
+#define TRACE_ADD3(hlp,fmt,a,b,c) \
+  _assuan_debug_add (_assuan_trace_context, &(hlp), fmt, (a), (b), (c))
+#define TRACE_END(hlp,fmt) \
+  _assuan_debug_add (_assuan_trace_context, &(hlp), fmt); \
+  _assuan_debug_end (_assuan_trace_context, &(hlp), _assuan_trace_level)
+#define TRACE_ENABLED(hlp) (!!(hlp))
+
+#endif	/* DEBUG_H */
diff --git a/src/libassuan.def b/src/libassuan.def
index a7ca5ee..59fe38c 100644
--- a/src/libassuan.def
+++ b/src/libassuan.def
@@ -24,64 +24,68 @@ EXPORTS
     assuan_close_input_fd		@3
     assuan_close_output_fd		@4
     assuan_command_parse_fd		@5
-    assuan_deinit_server		@6
-    assuan_disconnect			@7
-    assuan_end_confidential		@8
-    assuan_get_active_fds		@9
-    assuan_get_assuan_log_prefix	@10
-    assuan_get_assuan_log_stream	@11
-    assuan_get_data_fp			@12  
-    assuan_get_flag			@13  
-    assuan_get_input_fd			@14  
-    assuan_get_output_fd		@15  
-    assuan_get_pid			@16
-    assuan_get_pointer			@17
-    assuan_init_pipe_server		@18
-    assuan_init_socket_server		@19  
-    assuan_init_socket_server_ext	@20
-    assuan_inquire			@21
-    assuan_inquire_ext			@22
-    assuan_pending_line			@23
-    assuan_pipe_connect			@24
-    assuan_pipe_connect_ext		@25
-    assuan_process			@26
-    assuan_process_done			@27
-    assuan_process_next			@28
-    assuan_read_line			@29
-    assuan_receivefd			@30
-    assuan_register_bye_notify		@31
-    assuan_register_cancel_notify	@32
-    assuan_register_command		@33
-    assuan_register_input_notify	@34
-    assuan_register_option_handler	@35
-    assuan_register_output_notify	@36
-    assuan_register_post_cmd_notify	@37
-    assuan_register_reset_notify	@38
-    assuan_send_data			@39
-    assuan_sendfd			@40
-    assuan_set_assuan_err_source	@41
-    assuan_set_assuan_log_prefix	@42
-    assuan_set_assuan_log_stream	@43
-    assuan_set_error			@44
-    assuan_set_flag			@45
-    assuan_set_hello_line		@46
-    assuan_set_io_hooks			@47
-    assuan_set_io_monitor		@48
-    assuan_set_log_stream		@49
-    assuan_set_malloc_hooks		@50
-    assuan_set_okay_line		@51
-    assuan_set_pointer			@52
-    assuan_sock_bind			@53
-    assuan_sock_check_nonce		@54
-    assuan_sock_close			@55
-    assuan_sock_connect			@56
-    assuan_sock_get_nonce		@57
-    assuan_sock_new			@58
-    assuan_socket_connect		@59
-    assuan_socket_connect_ext		@60
-    assuan_transact			@61
-    assuan_write_line			@62
-    assuan_write_status			@63
+    assuan_end_confidential		@6
+    assuan_get_active_fds		@7
+    assuan_get_assuan_log_prefix	@8
+    assuan_get_assuan_log_stream	@9
+    assuan_get_data_fp			@10  
+    assuan_get_flag			@11  
+    assuan_get_gpg_err_source           @12
+    assuan_get_input_fd			@13  
+    assuan_get_log_cb                   @14
+    assuan_get_malloc_hooks             @15
+    assuan_get_output_fd		@16  
+    assuan_get_pid			@17
+    assuan_get_pointer			@18
+    assuan_init_pipe_server		@19
+    assuan_init_socket_server		@20  
+    assuan_init_socket_server_ext	@21
+    assuan_inquire			@22
+    assuan_inquire_ext			@23
+    assuan_new                          @24
+    assuan_new_ext                      @25
+    assuan_pending_line			@26
+    assuan_pipe_connect			@27
+    assuan_pipe_connect_ext		@28
+    assuan_process			@29
+    assuan_process_done			@30
+    assuan_process_next			@31
+    assuan_read_line			@32
+    assuan_receivefd			@33
+    assuan_register_bye_notify		@34
+    assuan_register_cancel_notify	@35
+    assuan_register_command		@36
+    assuan_register_input_notify	@37
+    assuan_register_option_handler	@38
+    assuan_register_output_notify	@39
+    assuan_register_post_cmd_notify	@40
+    assuan_register_reset_notify	@41
+    assuan_release                      @42
+    assuan_send_data			@43
+    assuan_sendfd			@44
+    assuan_set_assuan_log_prefix	@45
+    assuan_set_assuan_log_stream	@46
+    assuan_set_error			@47
+    assuan_set_flag			@48
+    assuan_set_gpg_err_source           @49
+    assuan_set_hello_line		@50
+    assuan_set_io_monitor		@51
+    assuan_set_log_cb                   @52
+    assuan_set_log_stream		@53
+    assuan_set_malloc_hooks		@54
+    assuan_set_okay_line		@55
+    assuan_set_pointer			@56
+    assuan_sock_bind			@57
+    assuan_sock_check_nonce		@58
+    assuan_sock_close			@59
+    assuan_sock_connect			@60
+    assuan_sock_get_nonce		@61
+    assuan_sock_new			@62
+    assuan_socket_connect		@63
+    assuan_socket_connect_ext		@64
+    assuan_transact			@65
+    assuan_write_line			@66
+    assuan_write_status			@67
 
 ; END
 
diff --git a/src/libassuan.vers b/src/libassuan.vers
index b139143..14c0cc7 100644
--- a/src/libassuan.vers
+++ b/src/libassuan.vers
@@ -27,8 +27,6 @@ LIBASSUAN_1.0 {
     assuan_close_input_fd;
     assuan_close_output_fd;
     assuan_command_parse_fd;
-    assuan_deinit_server;
-    assuan_disconnect;
     assuan_end_confidential;
     assuan_get_active_fds;
     assuan_get_assuan_log_prefix;
@@ -63,13 +61,11 @@ LIBASSUAN_1.0 {
     assuan_register_reset_notify;
     assuan_send_data;
     assuan_sendfd;
-    assuan_set_assuan_err_source;
     assuan_set_assuan_log_prefix;
     assuan_set_assuan_log_stream;
     assuan_set_error;
     assuan_set_flag;
     assuan_set_hello_line;
-    assuan_set_io_hooks;
     assuan_set_io_monitor;
     assuan_set_log_stream;
     assuan_set_malloc_hooks;
@@ -86,6 +82,16 @@ LIBASSUAN_1.0 {
     assuan_transact;
     assuan_write_line;
     assuan_write_status;
+    assuan_new;
+    assuan_release;
+    assuan_set_gpg_err_source;
+    assuan_get_gpg_err_source;
+    assuan_get_malloc_hooks;
+    assuan_set_log_cb;
+    assuan_get_log_cb;
+    assuan_new_ext;
+    assuan_new;
+    assuan_release;
 
   local:
     *;
diff --git a/src/system.c b/src/system.c
new file mode 100644
index 0000000..dd0c079
--- /dev/null
+++ b/src/system.c
@@ -0,0 +1,72 @@
+/* system.c - System support functions.
+   Copyright (C) 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 <stdlib.h>
+#include <errno.h>
+
+#include "assuan-defs.h"
+#include "debug.h"
+
+

+/* Manage memory specific to a context.  */
+
+void *
+_assuan_malloc (assuan_context_t ctx, size_t cnt)
+{
+  return ctx->malloc_hooks.malloc (cnt);
+}
+
+void *
+_assuan_realloc (assuan_context_t ctx, void *ptr, size_t cnt)
+{
+  return ctx->malloc_hooks.realloc (ptr, cnt);
+}
+
+void *
+_assuan_calloc (assuan_context_t ctx, size_t cnt, size_t elsize)
+{
+  void *ptr;
+  size_t nbytes;
+    
+  nbytes = cnt * elsize;
+
+  /* Check for overflow.  */
+  if (elsize && nbytes / elsize != cnt) 
+    {
+      errno = ENOMEM;
+      return NULL;
+    }
+
+  ptr = ctx->malloc_hooks.malloc (nbytes);
+  if (ptr)
+    memset (ptr, 0, nbytes);
+  return ptr;
+}
+
+void
+_assuan_free (assuan_context_t ctx, void *ptr)
+{
+  if (ptr)
+    ctx->malloc_hooks.free (ptr);
+}
diff --git a/tests/fdpassing.c b/tests/fdpassing.c
index fa26353..7197ff7 100644
--- a/tests/fdpassing.c
+++ b/tests/fdpassing.c
@@ -75,7 +75,7 @@ register_commands (assuan_context_t ctx)
   static struct
   {
     const char *name;
-    int (*handler) (assuan_context_t, char *line);
+    gpg_error_t (*handler) (assuan_context_t, char *line);
   } table[] =
       {
 	{ "ECHO", cmd_echo },
@@ -104,7 +104,11 @@ server (void)
 
   log_info ("server started\n");
 
-  rc = assuan_init_pipe_server (&ctx, NULL);
+  rc = assuan_new (&ctx);
+  if (rc)
+    log_fatal ("assuan_new failed: %s\n", gpg_strerror (rc));
+
+  rc = assuan_init_pipe_server (ctx, NULL);
   if (rc)
     log_fatal ("assuan_init_pipe_server failed: %s\n", gpg_strerror (rc));
 
@@ -132,7 +136,7 @@ server (void)
         log_error ("assuan_process failed: %s\n", gpg_strerror (rc));
     }
   
-  assuan_deinit_server (ctx);
+  assuan_release (ctx);
 }
 
 
@@ -193,7 +197,7 @@ client (assuan_context_t ctx, const char *fname)
   /* Give us some time to check with lsof that all descriptors are closed. */
 /*   sleep (10); */
 
-  assuan_disconnect (ctx);
+  assuan_release (ctx);
   return 0;
 }
 
@@ -210,7 +214,7 @@ main (int argc, char **argv)
 {
   int last_argc = -1;
   assuan_context_t ctx;
-  int err;
+  gpg_error_t err;
   int no_close_fds[2];
   const char *arglist[10];
   int is_server = 0;
@@ -260,7 +264,6 @@ main (int argc, char **argv)
 
 
   assuan_set_assuan_log_prefix (log_prefix);
-  assuan_set_assuan_log_stream (stderr);
 
   if (is_server)
     {
@@ -269,6 +272,8 @@ main (int argc, char **argv)
     }
   else
     {
+      const char *loc;
+
       no_close_fds[0] = 2;
       no_close_fds[1] = -1;
       if (with_exec)
@@ -278,8 +283,13 @@ main (int argc, char **argv)
           arglist[2] = verbose? "--verbose":NULL;
           arglist[3] = NULL;
         }
-      err = assuan_pipe_connect_ext (&ctx, with_exec? "./fdpassing":NULL,
-                                     with_exec? arglist :NULL,
+
+      err = assuan_new (&ctx);
+      if (err)
+	log_fatal ("assuan_new failed: %s\n", gpg_strerror (err));
+
+      err = assuan_pipe_connect_ext (ctx, with_exec? "./fdpassing":NULL,
+                                     with_exec ? arglist : &loc,
                                      no_close_fds, NULL, NULL, 1);
       if (err)
         {
@@ -287,7 +297,7 @@ main (int argc, char **argv)
           return 1;
         }
       
-      if (!ctx)
+      if (!with_exec && loc[0] == 's')
         {
           server ();
           log_info ("server finished\n");
@@ -297,12 +307,12 @@ main (int argc, char **argv)
           if (client (ctx, fname)) 
             {
               log_info ("waiting for server to terminate...\n");
-              assuan_disconnect (ctx);
+              assuan_release (ctx);
             }
           log_info ("client finished\n");
         }
     }
 
-  return errorcount? 1:0;
+  return errorcount ? 1 : 0;
 }
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-gnupg/libassuan.git



More information about the Pkg-gnupg-commit mailing list