From 5e00a176f502fe29d2f4d30d581865d539452f79 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 2 Aug 2007 14:59:01 +0000 Subject: [PATCH] Improved debug support: Assuan logging is now directed to the gpgme debug stream. Create processes detached. --- assuan/ChangeLog | 8 ++++++++ assuan/assuan-logging.c | 32 ++++++++++++++++++++++++++++++-- assuan/assuan-pipe-connect.c | 21 +++++++++++++++------ assuan/assuan.h | 9 +++++++++ gpgme/ChangeLog | 14 +++++++++++++- gpgme/debug.c | 34 ++++++++++++++++++++++++++++------ gpgme/debug.h | 3 +++ gpgme/gpgme.h | 4 ++-- gpgme/version.c | 19 +++++++++++++------ gpgme/w32-glib-io.c | 3 ++- gpgme/w32-io.c | 6 +++++- 11 files changed, 128 insertions(+), 25 deletions(-) diff --git a/assuan/ChangeLog b/assuan/ChangeLog index ada72ff..29e9ae2 100644 --- a/assuan/ChangeLog +++ b/assuan/ChangeLog @@ -1,3 +1,11 @@ +2007-08-02 Werner Koch + + * assuan-pipe-connect.c (pipe_connect_w32): A bit more debug output. + (pipe_connect_w32): Use DETACHED_PROCESS flag. + * assuan-logging.c (log_level): New. Use this to disable logging. + (assuan_set_assuan_log_level): New. + * assuan.h: Add prototype. + 2007-07-12 Werner Koch * assuan-handler.c (assuan_get_active_fds): Use get_osfhandle for diff --git a/assuan/assuan-logging.c b/assuan/assuan-logging.c index 5d4f2bb..41ada91 100644 --- a/assuan/assuan-logging.c +++ b/assuan/assuan-logging.c @@ -37,6 +37,23 @@ static char prefix_buffer[80]; static FILE *_assuan_log; static int full_logging; +static int log_level = 1; /* Defaults to logging enabled. */ + + +/* Set the log level for general assuan commands. 0 is no logging at + all, 1 is the standard logging and the default. Higher leveles may + be defined in the future. Passing a level of -1 will not change + the current log level. Returns previosu log level. */ +int +assuan_set_assuan_log_level (int level) +{ + int old = log_level; + + if (level != -1) + log_level = level; + return old; +} + void _assuan_set_default_log_stream (FILE *fp) @@ -105,6 +122,9 @@ _assuan_log_printf (const char *format, ...) FILE *fp; const char *prf; int save_errno = errno; + + if (!log_level) + return; fp = assuan_get_assuan_log_stream (); prf = assuan_get_assuan_log_prefix (); @@ -128,6 +148,9 @@ _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length) const unsigned char *s; int n; + if (!log_level) + return; + for (n=length,s=buffer; n; n--, s++) if ((!isascii (*s) || iscntrl (*s) || !isprint (*s)) && !(*s >= 0x80)) break; @@ -166,11 +189,16 @@ void _assuan_log_sanitized_string (const char *string) { const unsigned char *s = (const unsigned char *) string; - FILE *fp = assuan_get_assuan_log_stream (); + FILE *fp; - if (! *s) + if (!log_level) return; + if (!*s) + return; + + fp = assuan_get_assuan_log_stream (); + #ifdef HAVE_FLOCKFILE flockfile (fp); #endif diff --git a/assuan/assuan-pipe-connect.c b/assuan/assuan-pipe-connect.c index 867dc84..f21d850 100644 --- a/assuan/assuan-pipe-connect.c +++ b/assuan/assuan-pipe-connect.c @@ -641,6 +641,9 @@ create_inheritable_pipe (int filedes[2], int for_write) w = h; } + _assuan_log_printf ("created pipe: read=%p%s, write=%p%s\n", + r, for_write? " (inherit)":"", + w, for_write? "":" (inherit)"); filedes[0] = handle_to_fd (r); filedes[1] = handle_to_fd (w); return 0; @@ -752,6 +755,7 @@ pipe_connect_w32 (assuan_context_t *ctx, nullfd = CreateFile ("nul", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + _assuan_log_printf ("created nul device, hd=%p\n", nullfd); if (nullfd == INVALID_HANDLE_VALUE) { _assuan_log_printf ("can't open `nul': %s\n", w32_strerror (-1)); @@ -772,14 +776,17 @@ pipe_connect_w32 (assuan_context_t *ctx, /* Note: We inherit all handles flagged as inheritable. This seems to be a security flaw but there seems to be no way of selecting handles to inherit. */ - /* _assuan_log_printf ("CreateProcess, path=`%s' cmdline=`%s'\n", */ - /* name, cmdline); */ + _assuan_log_printf ("CreateProcess, path=`%s' cmdline=`%s'\n", + name, cmdline); + _assuan_log_printf (" stdin=%p stdout=%p stderr=%p\n", + si.hStdInput, si.hStdOutput, si.hStdError); if (!CreateProcess (name, /* Program to start. */ cmdline, /* Command line arguments. */ &sec_attr, /* Process security attributes. */ &sec_attr, /* Thread security attributes. */ TRUE, /* Inherit handles. */ (CREATE_DEFAULT_ERROR_MODE + | DETACHED_PROCESS | GetPriorityClass (GetCurrentProcess ()) | CREATE_SUSPENDED), /* Creation flags. */ NULL, /* Environment. */ @@ -807,13 +814,15 @@ pipe_connect_w32 (assuan_context_t *ctx, nullfd = INVALID_HANDLE_VALUE; } + _assuan_log_printf ("closing handles %p and %p\n", + fd_to_handle (rp[1]), fd_to_handle (wp[0]) ); CloseHandle (fd_to_handle (rp[1])); CloseHandle (fd_to_handle (wp[0])); - /* _assuan_log_printf ("CreateProcess ready: hProcess=%p hThread=%p" */ - /* " dwProcessID=%d dwThreadId=%d\n", */ - /* pi.hProcess, pi.hThread, */ - /* (int) pi.dwProcessId, (int) pi.dwThreadId); */ + _assuan_log_printf ("CreateProcess ready: hProcess=%p hThread=%p" + " dwProcessID=%d dwThreadId=%d\n", + pi.hProcess, pi.hThread, + (int) pi.dwProcessId, (int) pi.dwThreadId); ResumeThread (pi.hThread); CloseHandle (pi.hThread); diff --git a/assuan/assuan.h b/assuan/assuan.h index fd80795..cce9428 100644 --- a/assuan/assuan.h +++ b/assuan/assuan.h @@ -137,6 +137,7 @@ int _gpgme_io_recvmsg (int sock, struct msghdr *msg, int flags); #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_assuan_log_level _ASSUAN_PREFIX(assuan_set_assuan_log_level) #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) @@ -532,6 +533,14 @@ void assuan_set_assuan_err_source (int errsource); /*-- assuan-logging.c --*/ +/* Set the log level for general assuan commands. 0 is no logging at + all, 1 is the standard logging and the default. Higher leveles may + be defined in the future. Passing a level of -1 will not change + the current log level. Returns previous log level. Note, that + this function is not thread-safe and should in general be used + right at startup. */ +int assuan_set_assuan_log_level (int level); + /* 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 diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index 4ae4b2a..88006ac 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,3 +1,15 @@ +2007-08-02 Werner Koch + + * w32-glib-io.c (_gpgme_io_spawn): Use DETACHED_PROCESS flag. + * w32-io.c (_gpgme_io_spawn): Ditto. + (_gpgme_io_write): Map ERROR_NO_DATA to EPIPE. + * debug.c (_gpgme_debug): Enable assuan logging. + (_gpgme_debug_subsystem_init): New. * version.c + (do_subsystem_inits): Disable assuan logging and initialize de + debug system. + (gpgme_check_version): Do not trace before the subsystems are + initialized. + 2007-07-17 Marcus Brinkmann * debug.c:;5B Include and "debug.h". @@ -5394,7 +5406,7 @@ * data.c (gpgme_data_rewind): Allow to rewind data_type_none. - Copyright 2001, 2002, 2003, 2004, 2005 g10 Code GmbH + Copyright 2001,2002,2003,2004,2005,2006,2007 g10 Code GmbH This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without diff --git a/gpgme/debug.c b/gpgme/debug.c index 7280f63..bf1ca18 100644 --- a/gpgme/debug.c +++ b/gpgme/debug.c @@ -16,8 +16,8 @@ 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. */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ #if HAVE_CONFIG_H #include @@ -30,12 +30,16 @@ #include #include #ifndef HAVE_DOSISH_SYSTEM - #include - #include - #include +# include +# include +# include #endif #include +#ifdef HAVE_ASSUAN_H +#include "assuan.h" +#endif + #include "util.h" #include "sema.h" #include "debug.h" @@ -138,11 +142,29 @@ debug_init (void) } if (debug_level > 0) - fprintf (errfp, "gpgme_debug: level=%d\n", debug_level); + fprintf (errfp, "gpgme_debug: level=%d\n", debug_level); +#ifdef HAVE_ASSUAN_H + assuan_set_assuan_log_prefix ("gpgme-assuan"); + assuan_set_assuan_log_stream (errfp); + assuan_set_assuan_log_level (debug_level >= 0? debug_level:0); +#endif /* HAVE_ASSUAN_H*/ } UNLOCK (debug_lock); } + + +/* This should be called as soon as the locks are intialized. It is + required so that the assuan logging gets conncted to the gpgme log + stream as early as possible. */ +void +_gpgme_debug_subsystem_init (void) +{ + debug_init (); +} + + + /* Log the formatted string FORMAT at debug level LEVEL or higher. */ void diff --git a/gpgme/debug.h b/gpgme/debug.h index 72d6319..1083c66 100644 --- a/gpgme/debug.h +++ b/gpgme/debug.h @@ -50,6 +50,9 @@ _gpgme_debug_srcname (const char *file) return s? s+1:file; } +/* Called early to initialize the logging. */ +void _gpgme_debug_subsystem_init (void); + /* Log the formatted string FORMAT at debug level LEVEL or higher. */ void _gpgme_debug (int level, const char *format, ...); diff --git a/gpgme/gpgme.h b/gpgme/gpgme.h index 666041b..9ee8b07 100644 --- a/gpgme/gpgme.h +++ b/gpgme/gpgme.h @@ -16,8 +16,8 @@ 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. */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ #ifndef GPGME_H #define GPGME_H diff --git a/gpgme/version.c b/gpgme/version.c index 415b5f8..03d7aa0 100644 --- a/gpgme/version.c +++ b/gpgme/version.c @@ -55,18 +55,20 @@ do_subsystem_inits (void) return; _gpgme_sema_subsystem_init (); - _gpgme_io_subsystem_init (); #ifdef HAVE_ASSUAN_H + assuan_set_assuan_log_level (0); assuan_set_assuan_err_source (GPG_ERR_SOURCE_GPGME); -#ifdef HAVE_W32_SYSTEM +#endif /*HAVE_ASSUAN_H*/ + _gpgme_debug_subsystem_init (); +#if defined(HAVE_W32_SYSTEM) && defined(HAVE_ASSUAN_H) + _gpgme_io_subsystem_init (); /* We need to make sure that the sockets are initialized. */ { WSADATA wsadat; WSAStartup (0x202, &wsadat); } -#endif /*HAVE_W32_SYSTEM*/ -#endif /*HAVE_ASSUAN_H*/ +#endif /*HAVE_W32_SYSTEM && HAVE_ASSUAN_H*/ done = 1; } @@ -170,10 +172,15 @@ _gpgme_compare_versions (const char *my_version, const char * gpgme_check_version (const char *req_version) { + do_subsystem_inits (); + + /* Catch-22: We need to get at least the debug subsystem ready + before using the tarce facility. If we won't the tarce would + automagically initialize the debug system with out the locks + being initialized and missing the assuan log level setting. */ TRACE2 (DEBUG_INIT, "gpgme_check_version: ", 0, "req_version=%s, VERSION=%s", req_version, VERSION); - - do_subsystem_inits (); + return _gpgme_compare_versions (VERSION, req_version) ? VERSION : NULL; } diff --git a/gpgme/w32-glib-io.c b/gpgme/w32-glib-io.c index 9b3e0dc..232ed53 100644 --- a/gpgme/w32-glib-io.c +++ b/gpgme/w32-glib-io.c @@ -522,7 +522,8 @@ _gpgme_io_spawn (const char *path, char **argv, } } - cr_flags |= CREATE_SUSPENDED; + cr_flags |= CREATE_SUSPENDED; + cr_flags |= DETACHED_PROCESS; if (!CreateProcessA (path, arg_string, &sec_attr, /* process security attributes */ diff --git a/gpgme/w32-io.c b/gpgme/w32-io.c index 4a76d75..f745371 100644 --- a/gpgme/w32-io.c +++ b/gpgme/w32-io.c @@ -752,7 +752,10 @@ _gpgme_io_write (int fd, const void *buffer, size_t count) if (ctx->error) { UNLOCK (ctx->mutex); - errno = ctx->error_code; + if (ctx->error_code == ERROR_NO_DATA) + errno = EPIPE; + else + errno = EIO; return TRACE_SYSRES (-1); } @@ -1104,6 +1107,7 @@ _gpgme_io_spawn (const char *path, char **argv, } cr_flags |= CREATE_SUSPENDED; + cr_flags |= DETACHED_PROCESS; if (!CreateProcessA (path, arg_string, &sec_attr, /* process security attributes */ -- 2.26.2