[svn] assuan - r303 - in trunk: . doc src tests

svn author marcus cvs at cvs.gnupg.org
Mon Sep 21 03:08:08 CEST 2009


Author: marcus
Date: 2009-09-21 03:08:08 +0200 (Mon, 21 Sep 2009)
New Revision: 303

Added:
   trunk/src/assuan.c
   trunk/src/context.c
   trunk/src/conversion.c
   trunk/src/debug.c
   trunk/src/debug.h
   trunk/src/system.c
Modified:
   trunk/ChangeLog
   trunk/NEWS
   trunk/TODO
   trunk/configure.ac
   trunk/doc/ChangeLog
   trunk/doc/assuan.texi
   trunk/src/ChangeLog
   trunk/src/Makefile.am
   trunk/src/assuan-buffer.c
   trunk/src/assuan-client.c
   trunk/src/assuan-connect.c
   trunk/src/assuan-defs.h
   trunk/src/assuan-error.c
   trunk/src/assuan-handler.c
   trunk/src/assuan-inquire.c
   trunk/src/assuan-io-pth.c
   trunk/src/assuan-io.c
   trunk/src/assuan-listen.c
   trunk/src/assuan-logging.c
   trunk/src/assuan-pipe-connect.c
   trunk/src/assuan-pipe-server.c
   trunk/src/assuan-socket-connect.c
   trunk/src/assuan-socket-server.c
   trunk/src/assuan-uds.c
   trunk/src/assuan-util.c
   trunk/src/assuan.h
   trunk/src/libassuan.def
   trunk/src/libassuan.vers
   trunk/tests/fdpassing.c
Log:
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.


[The diff below has been truncated]

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2009-09-08 16:47:28 UTC (rev 302)
+++ trunk/ChangeLog	2009-09-21 01:08:08 UTC (rev 303)
@@ -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.

Modified: trunk/doc/ChangeLog
===================================================================
--- trunk/doc/ChangeLog	2009-09-08 16:47:28 UTC (rev 302)
+++ trunk/doc/ChangeLog	2009-09-21 01:08:08 UTC (rev 303)
@@ -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

Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog	2009-09-08 16:47:28 UTC (rev 302)
+++ trunk/src/ChangeLog	2009-09-21 01:08:08 UTC (rev 303)
@@ -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.

Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2009-09-08 16:47:28 UTC (rev 302)
+++ trunk/NEWS	2009-09-21 01:08:08 UTC (rev 303)
@@ -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)

Modified: trunk/TODO
===================================================================
--- trunk/TODO	2009-09-08 16:47:28 UTC (rev 302)
+++ trunk/TODO	2009-09-21 01:08:08 UTC (rev 303)
@@ -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.
 

Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac	2009-09-08 16:47:28 UTC (rev 302)
+++ trunk/configure.ac	2009-09-21 01:08:08 UTC (rev 303)
@@ -227,7 +227,8 @@
 
 # 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

Modified: trunk/doc/assuan.texi
===================================================================
--- trunk/doc/assuan.texi	2009-09-08 16:47:28 UTC (rev 302)
+++ trunk/doc/assuan.texi	2009-09-21 01:08:08 UTC (rev 303)
@@ -374,7 +374,7 @@
 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 @@
 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 @@
 @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 @@
 @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 @@
 @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 @@
 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 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.
+ 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.
 @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
+
+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}.
+ at 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 @@
 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);
 @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.
 @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);
+ at end smallexample
+ 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).
+
+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,9 +910,33 @@
 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 
 @c     C L I E N T   C O D E
 @c
@@ -683,18 +950,19 @@
 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 @@
 
 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,22 +1318,9 @@
 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.
-
 @end deftypefun
 
 @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}.
- at end deftypefun
-
- at noindent
 Now that everything has been setup, we can start to process our
 clients requests.
 
@@ -1354,32 +1609,6 @@
 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,35 +1718,7 @@
 @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}})
 
 This function returns the pid of the connected connected peer.  If that
@@ -1570,42 +1771,8 @@
 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
 @c     S O C K E T   W R A P P E R S
 @c

Modified: trunk/src/Makefile.am
===================================================================
--- trunk/src/Makefile.am	2009-09-08 16:47:28 UTC (rev 302)
+++ trunk/src/Makefile.am	2009-09-21 01:08:08 UTC (rev 303)
@@ -42,7 +42,11 @@
 
 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 \

Modified: trunk/src/assuan-buffer.c
===================================================================
--- trunk/src/assuan-buffer.c	2009-09-08 16:47:28 UTC (rev 302)
+++ trunk/src/assuan-buffer.c	2009-09-21 01:08:08 UTC (rev 303)
@@ -103,7 +103,7 @@
   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 @@
         }
 
       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_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 @@
 
       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 @@
                  (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 @@
   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 @@
         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 @@
       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 @@
   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 @@
         }
       
       
-      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 @@
             }
           *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 @@
   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 @@
 	}
       *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 @@
 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 @@
 #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)

Modified: trunk/src/assuan-client.c
===================================================================
--- trunk/src/assuan-client.c	2009-09-08 16:47:28 UTC (rev 302)
+++ trunk/src/assuan-client.c	2009-09-21 01:08:08 UTC (rev 303)
@@ -109,7 +109,7 @@
       *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 @@
   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_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 @@
   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);

Modified: trunk/src/assuan-connect.c
===================================================================
--- trunk/src/assuan-connect.c	2009-09-08 16:47:28 UTC (rev 302)
+++ trunk/src/assuan-connect.c	2009-09-21 01:08:08 UTC (rev 303)
@@ -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 @@
 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)

Modified: trunk/src/assuan-defs.h
===================================================================
--- trunk/src/assuan-defs.h	2009-09-08 16:47:28 UTC (rev 302)
+++ trunk/src/assuan-defs.h	2009-09-21 01:08:08 UTC (rev 303)
@@ -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,7 +45,10 @@
 
 #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
 {
   const char *name;
@@ -60,41 +69,72 @@
   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;
     int eof;
@@ -155,7 +195,7 @@
 
   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 @@
 
   /* 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);
+  void (*post_cmd_notify_fnc)(assuan_context_t, gpg_error_t);
 
-  /* 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);
 
   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 @@
 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,17 +282,9 @@
 
 
 /*-- assuan-logging.c --*/
-void _assuan_set_default_log_stream (FILE *fp);
+void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length);
 
-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);
 
-
 /*-- assuan-io.c --*/
 pid_t _assuan_waitpid (pid_t pid, int *status, int options);
 
@@ -322,4 +355,10 @@
 #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*/

Modified: trunk/src/assuan-error.c
===================================================================
--- trunk/src/assuan-error.c	2009-09-08 16:47:28 UTC (rev 302)
+++ trunk/src/assuan-error.c	2009-09-21 01:08:08 UTC (rev 303)
@@ -29,31 +29,7 @@
 #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.  */
 int
@@ -68,3 +44,20 @@
   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
+

Modified: trunk/src/assuan-handler.c
===================================================================
--- trunk/src/assuan-handler.c	2009-09-08 16:47:28 UTC (rev 302)
+++ trunk/src/assuan-handler.c	2009-09-21 01:08:08 UTC (rev 303)
@@ -27,9 +27,9 @@
 #include <errno.h>
 
 #include "assuan-defs.h"
+#include "debug.h"
 
 
-
 #define spacep(p)  (*(p) == ' ' || *(p) == '\t')
 #define digitp(a) ((a) >= '0' && (a) <= '9')
 
@@ -123,7 +123,7 @@
   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 @@
     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 @@
   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 @@
                                  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 @@
                             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 @@
                               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 @@
                                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 @@
 						   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 @@
                               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 @@
                               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 @@
 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 @@
   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 @@
       /* 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 @@
   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 @@
 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;




More information about the Gnupg-commits mailing list