aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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
28 files changed, 1824 insertions, 1175 deletions
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 <[email protected]>
+
+ * 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 <[email protected]>
* 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);
+}