summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Brinkmann <mb@g10code.com>2009-09-21 01:08:08 +0000
committerMarcus Brinkmann <mb@g10code.com>2009-09-21 01:08:08 +0000
commitcd87e56dac64c74d45f42838fc1049848f8aadcd (patch)
treeff70f9a6e8601305d06bebb55709350d3d8dbae4
parent0650eaa24a8a54dbfb1d5aea113ffd7a1536861a (diff)
downloadlibassuan-cd87e56dac64c74d45f42838fc1049848f8aadcd.tar.gz
2009-09-19 Marcus Brinkmann <marcus@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@g10code.de> * assuan.texi: Update to new API. src/ 2009-09-19 Marcus Brinkmann <marcus@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.
-rw-r--r--ChangeLog6
-rw-r--r--NEWS54
-rw-r--r--TODO3
-rw-r--r--configure.ac3
-rw-r--r--doc/ChangeLog4
-rw-r--r--doc/assuan.texi439
-rw-r--r--src/ChangeLog87
-rw-r--r--src/Makefile.am6
-rw-r--r--src/assuan-buffer.c86
-rw-r--r--src/assuan-client.c8
-rw-r--r--src/assuan-connect.c28
-rw-r--r--src/assuan-defs.h125
-rw-r--r--src/assuan-error.c41
-rw-r--r--src/assuan-handler.c55
-rw-r--r--src/assuan-inquire.c74
-rw-r--r--src/assuan-io-pth.c23
-rw-r--r--src/assuan-io.c25
-rw-r--r--src/assuan-listen.c16
-rw-r--r--src/assuan-logging.c156
-rw-r--r--src/assuan-pipe-connect.c281
-rw-r--r--src/assuan-pipe-server.c180
-rw-r--r--src/assuan-socket-connect.c92
-rw-r--r--src/assuan-socket-server.c57
-rw-r--r--src/assuan-uds.c27
-rw-r--r--src/assuan-util.c190
-rw-r--r--src/assuan.c177
-rw-r--r--src/assuan.h377
-rw-r--r--src/context.c127
-rw-r--r--src/conversion.c116
-rw-r--r--src/debug.c179
-rw-r--r--src/debug.h260
-rw-r--r--src/libassuan.def120
-rw-r--r--src/libassuan.vers14
-rw-r--r--src/system.c72
-rw-r--r--tests/fdpassing.c32
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@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@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@g10code.de>
+
+ * assuan.texi: Update to new API.
+
2009-09-01 Marcus Brinkmann <marcus@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.
-@item Use @code{assuan_set_assuan_log_stream} to setup a default log stream.
+@item If you use the default log handler, use
+@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
+@code{assuan_new} or @code{assuan_new_ext} and released with
+@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:
+
+@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:
+
+@table @code
+@item void *(*malloc) (size_t cnt)
+This is the function called by @sc{Assuan} to allocate memory for a context.
+
+@item void *(*realloc) (void *ptr, size_t cnt)
+This is the function called by @sc{Assuan} to reallocate memory for a context.
+
+@item void (*free) (void *ptr)
+This is the function called by @sc{Assuan} to release memory for a context.
+@end table
+@end deftp
+
+@deftp {Data type} {assuan_malloc_hooks_t}
+This is a pointer to a @code{struct assuan_malloc_hooks}.
+@end deftp
+
+/* Get the default malloc hooks. */
+assuan_malloc_hooks_t assuan_get_malloc_hooks (void);
+
+@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
+
+@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.
+@end deftypefun
-@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.
+
+@anchor{function assuan_set_gpg_err_source}
+@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
+@smallexample
+assuan_set_assuan_err_source (GPG_ERR_SOURCE_DEFAULT);
+@end smallexample
+@end deftypefun
+
+@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:
+@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
+@var{hook_value} that was supplied when the log handler was registered
+for the context with @code{assuan_set_log_cb}, and a category
+@var{cat}. The category is one of:
+
+@table @code
+@item ASSUAN_LOG_INIT
+@item ASSUAN_LOG_CTX
+@item ASSUAN_LOG_ENGINE
+@item ASSUAN_LOG_DATA
+@item ASSUAN_LOG_SYSIO
+@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.
+@end deftp
+
+@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}.
+@end deftypefun
+
+@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}.
+@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.
+
+@node Default Log Handler
+@section Default Log Handler
+
+The default log handler can be configured by the following functions:
+
+@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.
+@end deftypefun
+
+
+@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.
+@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
-@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.
+
+@deftypefun @w{FILE *} assuan_get_assuan_log_stream (void)
+Return the stream which is currently being using for global logging.
@end deftypefun
-@anchor{function assuan_set_assuan_err_source}
-@deftypefun void assuan_set_assuan_err_source (@w{int @var{errsource}})
-Set the error source for error values generated by @code{libassuan}.
-@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.
+
+@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
+
+
+@node Contexts
+@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
+@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.
+
+@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
+@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
+
+@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}.
+@end deftypefun
+
+After the context has been used, it can be destroyed again.
+
+@deftypefun void assuan_release (assuan_context_t ctx)
+The function @code{assuan_release} destroys the context CTX and
+releases all associated resources.
+@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:
+
+@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
+@var{ctx}. This is useful to provide command handlers with additional
+application context.
+@end deftypefun
+
+@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:
+@smallexample
+static int
+cmd_foo (assuan_context_t ctx, char *line)
+@{
+ ctrl_t ctrl = assuan_get_pointer (ctx);
+ ...
+@}
+@end smallexample
+@end deftypefun
+
+
+@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.
+
+@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:
+
+@table @code
+@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.
+@item ASSUAN_CONFIDENTIAL
+Uses to return the state of the confidential logging mode.
+@end table
+@end deftp
+@end deftypefun
+
+@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}.
+@end deftypefun
+
+
+@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:
+@smallexample
+assuan_set_flag (ctx, ASSUAN_CONFIDENTIAL, 1);
@end smallexample
@end deftypefun
+
+@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:
+@smallexample
+assuan_set_flag (ctx, ASSUAN_CONFIDENTIAL, 0);
+@end smallexample
+@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.
+@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
+@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:
+
+@table @code
+@item ASSUAN_IO_MONITOR_NOLOG
+Active logging of this line is suppressed. This can reduce debug
+output in the case of a frequent message.
+@item ASSUAN_IO_MONITOR_IGNORE
+The whole output line is discarded.
+@end table
+@end deftp
+
+@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}.
+@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:
-@deftypefun gpg_error_t assuan_pipe_connect_ext (@w{assuan_context_t *@var{ctx}},@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}})
+@deftypefun gpg_error_t assuan_pipe_connect_ext (@w{assuan_context_t *@var{ctx}},@w{const char *@var{name}}, @w{const char *@var{argv}[]}, @w{int *@var{fd_child_list}}, @w{void (*@var{atfork}) (void *, int)}, @w{void *@var{atforkvalue}}, @w{unsigned int @var{flags}})
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:
-@deftypefun gpg_error_t assuan_pipe_connect (@w{assuan_context_t *@var{ctx}},@w{const char *@var{name}}, @w{const char *const @var{argv}[]}, @w{int *@var{fd_child_list}})
+@deftypefun gpg_error_t assuan_pipe_connect (@w{assuan_context_t *@var{ctx}},@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.
-
-@end deftypefun
-
-@noindent
-As a last initialization step, debugging may be enabled for the
-current connection. This is done using
-
-@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.
-
-@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
-@var{ctx}. This is useful to provide command handlers with additional
-application context.
-@end deftypefun
-
-@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:
-@smallexample
-static int
-cmd_foo (assuan_context_t ctx, char *line)
-@{
- ctrl_t ctrl = assuan_get_pointer (ctx);
- ...
-@}
-@end smallexample
-@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
-@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.
-
-@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:
-
-@table @code
-@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.
-@item ASSUAN_CONFIDENTIAL
-Uses to return the state of the confidential logging mode. For changing
-this mode the functions @code{assuan_begin_confidential} and
-@code{assuan_end_confidential} should be used.
-@end table
-@end deftp
-
-@end deftypefun
-
-@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}.
-@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
-@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.
-@end deftypefun
-
-@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.
-@end deftypefun
-
-@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).
-@end deftypefun
-
-@deftypefun FILE* assuan_get_assuan_log_stream (void)
-
-Return the stream which is currently being using for global logging.
-@end deftypefun
-
-@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.
-@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@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@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;
}