diff --git a/NEWS b/NEWS index 370220d..7068cb2 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,8 @@ Version 1.2.3 (unreleased) + o Added libssh2_trace_sethandler() + o Added the direct_tcpip.c example + o Fixed memory leak in userauth_publickey o Added support for authentication via SSH-Agent. By Daiki Ueno. Version 1.2.2 (November 16, 2009) diff --git a/docs/Makefile.am b/docs/Makefile.am index 7b0db51..40a8938 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -97,6 +97,7 @@ dist_man_MANS = \ libssh2_sftp_unlink_ex.3 \ libssh2_sftp_write.3 \ libssh2_trace.3 \ + libssh2_trace_sethandler.3 \ libssh2_userauth_authenticated.3 \ libssh2_userauth_hostbased_fromfile_ex.3 \ libssh2_userauth_keyboard_interactive_ex.3 \ diff --git a/docs/libssh2_trace_sethandler.3 b/docs/libssh2_trace_sethandler.3 index 7d57800..a039a79 100644 --- a/docs/libssh2_trace_sethandler.3 +++ b/docs/libssh2_trace_sethandler.3 @@ -1,19 +1,26 @@ .\" $Id: libssh2_trace_sethandler.3,v 1.1 2008/12/26 07:46:45 bagder Exp $ .\" -.TH libssh2_trace_sethandler 3 "03 Nov 2009" "libssh2 1.2" "libssh2 manual" +.TH libssh2_trace_sethandler 3 "15 Jan 2010" "libssh2 1.2.3" "libssh2 manual" .SH NAME libssh2_trace_sethandler - set a trace output handler .SH SYNOPSIS +.nf #include -typedef void (*libssh2_trace_handler_func)(LIBSSH2_SESSION*, const char*, size_t); - -LIBSSH2_API int libssh2_trace_sethandler(LIBSSH2_SESSION *session, libssh2_trace_handler_func callback); +typedef void (*libssh2_trace_handler_func)(LIBSSH2_SESSION *session, + const char *data, + size_t length); +int libssh2_trace_sethandler(LIBSSH2_SESSION *session, + libssh2_trace_handler_func callback); .SH DESCRIPTION -This function can be called to install a trace output handler for your application. By default, when -tracing has been switched on via a call to libssh2_trace(), any output is written to stderr. By calling -this method and passing a function pointer that matches the libssh2_trace_handler_func prototype, libssh2 -will call back as it generates trace output. This can be used to capture the trace output and put it into -a log file or diagnostic window. This function has no effect unless libssh2 was built to support -this option, and a typical "release build" might not. +libssh2_trace_sethandler installs a trace output handler for your application. +By default, when tracing has been switched on via a call to libssh2_trace(), +all output is written to stderr. By calling this method and passing a +function pointer that matches the libssh2_trace_handler_func prototype, +libssh2 will call back as it generates trace output. This can be used to +capture the trace output and put it into a log file or diagnostic window. +This function has no effect unless libssh2 was built to support this option, +and a typical "release build" might not. +.SH AVAILABILITY +Added in libssh2 version 1.2.3 diff --git a/include/libssh2.h b/include/libssh2.h index 3c65902..39817d3 100644 --- a/include/libssh2.h +++ b/include/libssh2.h @@ -987,6 +987,11 @@ LIBSSH2_API int libssh2_trace(LIBSSH2_SESSION *session, int bitmask); #define LIBSSH2_TRACE_PUBLICKEY (1<<8) #define LIBSSH2_TRACE_SOCKET (1<<9) +typedef void (*libssh2_trace_handler_func)(LIBSSH2_SESSION*, const char *, + size_t); +LIBSSH2_API int libssh2_trace_sethandler(LIBSSH2_SESSION *session, + libssh2_trace_handler_func callback); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h index 1ba9354..8f26efb 100644 --- a/src/libssh2_priv.h +++ b/src/libssh2_priv.h @@ -735,6 +735,7 @@ struct _LIBSSH2_SESSION struct transportpacket packet; #ifdef LIBSSH2DEBUG int showmask; /* what debug/trace messages to display */ + libssh2_trace_handler_func tracehandler; /* callback to display trace messages */ #endif /* State variables used in libssh2_banner_send() */ diff --git a/src/misc.c b/src/misc.c index d5ebf6c..3b55806 100644 --- a/src/misc.c +++ b/src/misc.c @@ -312,6 +312,13 @@ libssh2_trace(LIBSSH2_SESSION * session, int bitmask) return 0; } +LIBSSH2_API int +libssh2_trace_sethandler(LIBSSH2_SESSION *session, libssh2_trace_handler_func callback) +{ + session->tracehandler = callback; + return 0; +} + void _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...) { @@ -353,8 +360,12 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...) len += vsnprintf(buffer + len, 1535 - len, format, vargs); buffer[len] = '\n'; va_end(vargs); - write(2, buffer, len + 1); + if (session->tracehandler) { + (session->tracehandler)(session, buffer, len + 1); + } else { + write(2, buffer, len + 1); + } } #else @@ -365,6 +376,14 @@ libssh2_trace(LIBSSH2_SESSION * session, int bitmask) (void) bitmask; return 0; } + +LIBSSH2_API int +libssh2_trace_sethandler(LIBSSH2_SESSION *session, libssh2_trace_handler_func callback) +{ + (void) session; + (void) callback; + return 0; +} #endif /* init the list head */ diff --git a/src/transport.c b/src/transport.c index 5a2dfeb..0be694d 100644 --- a/src/transport.c +++ b/src/transport.c @@ -41,6 +41,7 @@ #include "libssh2_priv.h" #include #include +#include #include @@ -57,36 +58,56 @@ debugdump(LIBSSH2_SESSION * session, { size_t i; size_t c; - FILE *stream = stderr; unsigned int width = 0x10; + char buffer[256]; /* Must be enough for width*4 + about 30 or so */ + size_t used; + static const char* hex_chars = "0123456789ABCDEF"; if (!(session->showmask & LIBSSH2_TRACE_TRANS)) { /* not asked for, bail out */ return; } - fprintf(stream, "=> %s (%d bytes)\n", desc, (int) size); + used = snprintf(buffer, sizeof(buffer), "=> %s (%d bytes)\n", + desc, (int) size); + if (session->tracehandler) + (session->tracehandler)(session, buffer, used); + else + write(2 /* stderr */, buffer, used); for(i = 0; i < size; i += width) { - fprintf(stream, "%04lx: ", (long)i); + used = snprintf(buffer, sizeof(buffer), "%04lx: ", (long)i); /* hex not disabled, show it */ for(c = 0; c < width; c++) { - if (i + c < size) - fprintf(stream, "%02x ", ptr[i + c]); - else - fputs(" ", stream); + if (i + c < size) { + buffer[used++] = hex_chars[(ptr[i+c] >> 4) & 0xF]; + buffer[used++] = hex_chars[ptr[i+c] & 0xF]; + } + else { + buffer[used++] = ' '; + buffer[used++] = ' '; + } + + buffer[used++] = (c == (width/2)-1) ? ':' : ' '; } + buffer[used++] = ':'; + buffer[used++] = ' '; + for(c = 0; (c < width) && (i + c < size); c++) { - fprintf(stream, "%c", - (ptr[i + c] >= 0x20) && - (ptr[i + c] < 0x80) ? ptr[i + c] : UNPRINTABLE_CHAR); + buffer[used++] = isprint(ptr[i + c]) ? + ptr[i + c] : UNPRINTABLE_CHAR; } - fputc('\n', stream); /* newline */ + buffer[used++] = '\n'; + buffer[used] = 0; + + if (session->tracehandler) + (session->tracehandler)(session, buffer, used); + else + write(2, buffer, used); } - fflush(stream); } #else #define debugdump(a,x,y,z)