diff options
-rw-r--r-- | debian/libwsutil0.symbols | 2 | ||||
-rw-r--r-- | dumpcap.c | 36 | ||||
-rw-r--r-- | ui/console.c | 12 | ||||
-rw-r--r-- | ui/console.h | 3 | ||||
-rw-r--r-- | wsutil/wslog.c | 191 | ||||
-rw-r--r-- | wsutil/wslog.h | 21 |
6 files changed, 161 insertions, 104 deletions
diff --git a/debian/libwsutil0.symbols b/debian/libwsutil0.symbols index 3449ab932b..d9ea8f3d8e 100644 --- a/debian/libwsutil0.symbols +++ b/debian/libwsutil0.symbols @@ -227,8 +227,8 @@ libwsutil.so.0 libwsutil0 #MINVER# ws_init_sockets@Base 3.1.0 ws_log@Base 3.5.0 ws_log_add_custom_file@Base 3.5.0 - ws_log_default_writer@Base 3.5.0 ws_log_domain_to_string@Base 3.5.0 + ws_log_fprint@Base 3.5.0 ws_log_full@Base 3.5.0 ws_log_get_level@Base 3.5.0 ws_log_init@Base 3.5.0 @@ -327,8 +327,11 @@ static gboolean need_timeout_workaround; #define WRITER_THREAD_TIMEOUT 100000 /* usecs */ static void -dumpcap_log_writer(const char *message, enum ws_log_domain domain, - enum ws_log_level level, void *ptr); +dumpcap_log_writer(const char *format, va_list ap, + const char *prefix, + enum ws_log_domain domain, + enum ws_log_level level, + void *user_data); /* capture related options */ static capture_options global_capture_opts; @@ -5567,29 +5570,30 @@ main(int argc, char *argv[]) } static void -dumpcap_log_writer(const char *message, enum ws_log_domain domain _U_, - enum ws_log_level level _U_, void *ptr _U_) +dumpcap_log_writer(const char *format, va_list ap, + const char *prefix, + enum ws_log_domain domain _U_, + enum ws_log_level level _U_, + void *user_data _U_) { #if defined(DEBUG_DUMPCAP) || defined(DEBUG_CHILD_DUMPCAP) #ifdef DEBUG_DUMPCAP - fprintf(stderr, "%s\n", message); - fflush(stderr); + ws_log_fprint(stderr, format, ap, prefix); #endif #ifdef DEBUG_CHILD_DUMPCAP - fprintf(debug_log, "%s\n", message); - fflush(debug_log); -#endif - return; + ws_log_fprint(debug_log, format, ap, prefix); #endif - - /* Messages goto stderr or */ - /* to parent especially formatted if dumpcap running as child. */ +#else + /* Messages goto stderr or to parent especially formatted if dumpcap + * is running as child. */ if (capture_child) { - sync_pipe_errmsg_to_parent(2, message, ""); + gchar *msg = g_strdup_vprintf(format, ap); + sync_pipe_errmsg_to_parent(2, msg, ""); + g_free(msg); } else { - fprintf(stderr, "%s", message); - fflush(stderr); + ws_log_fprint(stderr, format, ap, prefix); } +#endif } diff --git a/ui/console.c b/ui/console.c index 1a1af2ebd7..cb3a62ea73 100644 --- a/ui/console.c +++ b/ui/console.c @@ -19,8 +19,9 @@ #include "console.h" void -console_log_writer(const char *message, enum ws_log_domain domain _U_, - enum ws_log_level level, void *ptr _U_) +console_log_writer(const char *format, va_list ap, + const char *prefix, enum ws_log_domain domain _U_, + enum ws_log_level level _U_, void *ptr _U_) { gboolean fatal = level == LOG_LEVEL_ERROR; #ifdef _WIN32 @@ -32,12 +33,7 @@ console_log_writer(const char *message, enum ws_log_domain domain _U_, (void)fatal; #endif /* _WIN32 */ - FILE *fp = stderr; - g_assert(message); - - fputs(message, fp); - fputc('\n', fp); - fflush(fp); + ws_log_fprint(stderr, format, ap, prefix); #ifdef _WIN32 if (fatal) { diff --git a/ui/console.h b/ui/console.h index 196ef231f9..6760efa15b 100644 --- a/ui/console.h +++ b/ui/console.h @@ -26,7 +26,8 @@ extern "C" { /** The GUI log writer. */ void -console_log_writer(const char *message, enum ws_log_domain domain, +console_log_writer(const char *format, va_list ap, + const char *prefix, enum ws_log_domain domain, enum ws_log_level level, void *ptr); #ifdef __cplusplus diff --git a/wsutil/wslog.c b/wsutil/wslog.c index ee93565437..00eeab1e62 100644 --- a/wsutil/wslog.c +++ b/wsutil/wslog.c @@ -18,7 +18,7 @@ #include <wsutil/ws_assert.h> #include <wsutil/time_util.h> -#define LOGBUFSIZE 256 +#define PREFIX_BUFSIZE 128 #define LOGENVVAR "WS_LOG_LEVEL" @@ -27,11 +27,11 @@ static enum ws_log_level current_log_level = LOG_LEVEL_MESSAGE; -static ws_log_writer_t *current_log_writer = ws_log_default_writer; +static ws_log_writer_cb *registered_log_writer = NULL; -static void *current_log_writer_data = NULL; +static void *registered_log_writer_data = NULL; -static ws_log_writer_free_data_t *current_log_writer_data_free = NULL; +static ws_log_writer_free_data_cb *registered_log_writer_data_free = NULL; static FILE *custom_log = NULL; @@ -39,26 +39,17 @@ static FILE *custom_log = NULL; static void ws_log_cleanup(void); -static void -log_default_writer_do_work(FILE *fp, const char *message) +void +ws_log_fprint(FILE *fp, const char *format, va_list ap, + const char *prefix) { - ws_assert(message); - fputs(message, fp); + fputs(prefix, fp); + vfprintf(fp, format, ap); fputc('\n', fp); fflush(fp); } -void -ws_log_default_writer(const char *message, - enum ws_log_domain domain _U_, - enum ws_log_level level _U_, - void *user_data _U_) -{ - log_default_writer_do_work(stderr, message); -} - - const char *ws_log_level_to_string(enum ws_log_level level) { switch (level) { @@ -213,10 +204,10 @@ const char *ws_log_set_level_args(int *argc_ptr, char *argv[]) } -void ws_log_init(ws_log_writer_t *_writer) +void ws_log_init(ws_log_writer_cb *_writer) { if (_writer) { - current_log_writer = _writer; + registered_log_writer = _writer; } const char *env = g_getenv(LOGENVVAR); @@ -228,32 +219,32 @@ void ws_log_init(ws_log_writer_t *_writer) } -void ws_log_init_with_data(ws_log_writer_t *writer, void *user_data, - ws_log_writer_free_data_t *free_user_data) +void ws_log_init_with_data(ws_log_writer_cb *writer, void *user_data, + ws_log_writer_free_data_cb *free_user_data) { - current_log_writer_data = user_data; - current_log_writer_data_free = free_user_data; + registered_log_writer_data = user_data; + registered_log_writer_data_free = free_user_data; ws_log_init(writer); } -static inline const char *_level_to_string(enum ws_log_level level) +static inline const char *_lvl_to_str(enum ws_log_level level) { switch (level) { - case LOG_LEVEL_NONE: return "NUL"; - case LOG_LEVEL_ERROR: return "ERR"; - case LOG_LEVEL_CRITICAL: return "CRI"; - case LOG_LEVEL_WARNING: return "WRN"; - case LOG_LEVEL_MESSAGE: return "MSG"; - case LOG_LEVEL_INFO: return "NFO"; - case LOG_LEVEL_DEBUG: return "DBG"; + case LOG_LEVEL_NONE: return "(NONE)"; + case LOG_LEVEL_ERROR: return "ERROR"; + case LOG_LEVEL_CRITICAL: return "CRITICAL"; + case LOG_LEVEL_WARNING: return "WARNING"; + case LOG_LEVEL_MESSAGE: return "MESSAGE"; + case LOG_LEVEL_INFO: return "INFO"; + case LOG_LEVEL_DEBUG: return "DEBUG"; default: return "(BOGUS LOG LEVEL)"; } } -static inline const char *_domain_to_string(enum ws_log_domain domain) +static inline const char *_dom_to_str(enum ws_log_domain domain) { switch (domain) { case LOG_DOMAIN_DEFAULT: return "Dflt"; @@ -270,43 +261,113 @@ static inline const char *_domain_to_string(enum ws_log_domain domain) } -static void ws_log_writev(enum ws_log_domain domain, enum ws_log_level level, - const char *location, const char *format, va_list ap) +struct logstr { + char buffer[PREFIX_BUFSIZE]; + char *ptr; + int free; +}; + + +static inline void logstr_init(struct logstr *str) +{ + str->free = (int)(sizeof(str->buffer) - 1); + str->buffer[sizeof(str->buffer) - 1] = '\0'; + str->ptr = str->buffer; + +#ifndef WS_DISABLE_ASSERT + memset(str->buffer, 0, sizeof(str->buffer)); +#endif +} + + +static inline int logstr_snprintf(struct logstr *str, const char *fmt, ...) +{ + int write; + va_list ap; + + if (str->free <= 0) + return -1; + + va_start(ap, fmt); + write = vsnprintf(str->ptr, str->free, fmt, ap); + va_end(ap); + + if (write < 0 || write >= str->free) { + str->ptr = NULL; + str->free = -1; + return -1; + } + + str->ptr += write; + ws_assert(str->ptr < str->buffer + sizeof(str->buffer)); + str->free -= write; + ws_assert(str->free > 0); + return 0; +} + + +static void create_log_time(struct logstr *str) { - char timestamp[sizeof("00:00:00.000")]; - char user_string[LOGBUFSIZE]; - char message[LOGBUFSIZE*2]; time_t curr; struct tm *today; + guint64 microseconds; - /* create a "timestamp" */ time(&curr); today = localtime(&curr); - guint64 microseconds = create_timestamp(); - if (today != NULL) { - snprintf(timestamp, sizeof(timestamp), "%02d:%02d:%02d.%03" G_GUINT64_FORMAT, - today->tm_hour, today->tm_min, today->tm_sec, - microseconds % 1000000 / 1000); - } - else { - snprintf(timestamp, sizeof(timestamp), "(notime)"); + microseconds = create_timestamp(); + + if (G_UNLIKELY(today == NULL)) { + logstr_snprintf(str, " ** "); + return; } - vsnprintf(user_string, sizeof(user_string), format, ap); + logstr_snprintf(str, " ** %02d:%02d:%02d.%03" G_GUINT64_FORMAT, + today->tm_hour, today->tm_min, today->tm_sec, + microseconds % 1000000 / 1000); +} + - snprintf(message, sizeof(message), "%s %s-%s %s : %s", - timestamp, - _domain_to_string(domain), - _level_to_string(level), - location ? location : "(nofile)", - user_string); +static void logstr_prefix_print(struct logstr *str, + enum ws_log_domain domain, enum ws_log_level level, + const char *file, int line, const char *func) +{ + create_log_time(str); + + logstr_snprintf(str, " [%s-%s]", _dom_to_str(domain), _lvl_to_str(level)); + + if (func) + logstr_snprintf(str, " %s()", func); + else if (file && line >= 0) + logstr_snprintf(str, " (%d)%s", file, line); + else if (file) + logstr_snprintf(str, " %s", file); + + logstr_snprintf(str, " -- "); +} + + +static void log_internal_write(enum ws_log_domain domain, enum ws_log_level level, + const char *file, int line, const char *func, + const char *user_format, va_list user_ap) +{ + struct logstr prefix; + + logstr_init(&prefix); + + logstr_prefix_print(&prefix, domain, level, file, line, func); /* Call the registered writer, or the default if one wasn't registered. */ - current_log_writer(message, domain, level, current_log_writer_data); + if (registered_log_writer) { + registered_log_writer(user_format, user_ap, prefix.buffer, + domain, level, registered_log_writer_data); + } + else { + ws_log_fprint(stderr, user_format, user_ap, prefix.buffer); + } /* If we have a custom file, write to it _also_. */ if (custom_log) { - log_default_writer_do_work(custom_log, message); + ws_log_fprint(custom_log, user_format, user_ap, prefix.buffer); } if (level == LOG_LEVEL_ERROR) { @@ -322,7 +383,7 @@ void ws_logv(enum ws_log_domain domain, enum ws_log_level level, if (!ws_log_level_is_active(level)) return; - ws_log_writev(domain, level, NULL, format, ap); + log_internal_write(domain, level, NULL, -1, NULL, format, ap); } @@ -335,7 +396,7 @@ void ws_log(enum ws_log_domain domain, enum ws_log_level level, return; va_start(ap, format); - ws_log_writev(domain, level, NULL, format, ap); + log_internal_write(domain, level, NULL, -1, NULL, format, ap); va_end(ap); } @@ -345,27 +406,21 @@ void ws_log_full(enum ws_log_domain domain, enum ws_log_level level, const char *format, ...) { va_list ap; - char location[LOGBUFSIZE]; if (!ws_log_level_is_active(level)) return; - if (func) - snprintf(location, sizeof(location), "%s(%d) %s()", file, line, func); - else - snprintf(location, sizeof(location), "%s(%d)", file, line); - va_start(ap, format); - ws_log_writev(domain, level, location, format, ap); + log_internal_write(domain, level, file, line, func, format, ap); va_end(ap); } static void ws_log_cleanup(void) { - if (current_log_writer_data_free) { - current_log_writer_data_free(current_log_writer_data); - current_log_writer_data = NULL; + if (registered_log_writer_data_free) { + registered_log_writer_data_free(registered_log_writer_data); + registered_log_writer_data = NULL; } if (custom_log) { fclose(custom_log); diff --git a/wsutil/wslog.h b/wsutil/wslog.h index 9f9bcc7f7f..6fa4f66a42 100644 --- a/wsutil/wslog.h +++ b/wsutil/wslog.h @@ -40,21 +40,22 @@ enum ws_log_level { #endif -/** Signature for registering a log writer. */ -typedef void (ws_log_writer_t)(const char *message, +/** Callback for registering a log writer. */ +typedef void (ws_log_writer_cb)(const char *format, va_list ap, + const char *prefix, enum ws_log_domain domain, enum ws_log_level level, void *user_data); -typedef void (ws_log_writer_free_data_t)(void *user_data); +/** Callback for freeing a user data pointer. */ +typedef void (ws_log_writer_free_data_cb)(void *user_data); +/** Writes to stream a new log line and flushes. */ WS_DLL_PUBLIC -void ws_log_default_writer(const char *message, - enum ws_log_domain domain, - enum ws_log_level level, - void *user_data); +void ws_log_fprint(FILE *fp, const char *format, va_list ap, + const char *prefix); /** Convert a numerical level to its string representation. */ @@ -114,7 +115,7 @@ const char *ws_log_set_level_args(int *argcp, char **argv); * is NULL the default log writer is used. */ WS_DLL_PUBLIC -void ws_log_init(ws_log_writer_t *writer); +void ws_log_init(ws_log_writer_cb *writer); /** Initializes the logging code. @@ -124,8 +125,8 @@ void ws_log_init(ws_log_writer_t *writer); * is passed it will be called with user_data when the program terminates. */ WS_DLL_PUBLIC -void ws_log_init_with_data(ws_log_writer_t *writer, void *user_data, - ws_log_writer_free_data_t *free_user_data); +void ws_log_init_with_data(ws_log_writer_cb *writer, void *user_data, + ws_log_writer_free_data_cb *free_user_data); /** This function is called to output a message to the log. |