diff options
author | Martin Willi <martin@revosec.ch> | 2013-09-27 17:30:17 +0200 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2013-10-11 11:05:30 +0200 |
commit | 243048248b7c885186201a112484378b43116f66 (patch) | |
tree | ffdb81423ff050897c959244f390d5cbe8442694 | |
parent | 11282d0054d8a51f184a6f726f7f180ccf60e456 (diff) | |
download | strongswan-243048248b7c885186201a112484378b43116f66.tar.bz2 strongswan-243048248b7c885186201a112484378b43116f66.tar.xz |
printf-hook: Move glibc/vstr printf hook backends to separate files
-rw-r--r-- | src/libstrongswan/Android.mk | 2 | ||||
-rw-r--r-- | src/libstrongswan/Makefile.am | 11 | ||||
-rw-r--r-- | src/libstrongswan/library.h | 2 | ||||
-rw-r--r-- | src/libstrongswan/utils/enum.h | 2 | ||||
-rw-r--r-- | src/libstrongswan/utils/printf_hook.h | 247 | ||||
-rw-r--r-- | src/libstrongswan/utils/printf_hook/printf_hook.h | 119 | ||||
-rw-r--r-- | src/libstrongswan/utils/printf_hook/printf_hook_glibc.c | 244 | ||||
-rw-r--r-- | src/libstrongswan/utils/printf_hook/printf_hook_vstr.c (renamed from src/libstrongswan/utils/printf_hook.c) | 259 | ||||
-rw-r--r-- | src/libstrongswan/utils/printf_hook/printf_hook_vstr.h | 83 |
9 files changed, 586 insertions, 383 deletions
diff --git a/src/libstrongswan/Android.mk b/src/libstrongswan/Android.mk index 3811ed083..74b409608 100644 --- a/src/libstrongswan/Android.mk +++ b/src/libstrongswan/Android.mk @@ -35,7 +35,7 @@ selectors/traffic_selector.c threading/thread.c threading/thread_value.c \ threading/mutex.c threading/semaphore.c threading/rwlock.c threading/spinlock.c \ utils/utils.c utils/chunk.c utils/debug.c utils/enum.c utils/identification.c \ utils/lexparser.c utils/optionsfrom.c utils/capabilities.c utils/backtrace.c \ -utils/printf_hook.c utils/settings.c +utils/printf_hook/printf_hook_vstr.c utils/settings.c # adding the plugin source files diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am index 78e4ce2e1..c0f8c39dc 100644 --- a/src/libstrongswan/Makefile.am +++ b/src/libstrongswan/Makefile.am @@ -33,7 +33,7 @@ selectors/traffic_selector.c threading/thread.c threading/thread_value.c \ threading/mutex.c threading/semaphore.c threading/rwlock.c threading/spinlock.c \ utils/utils.c utils/chunk.c utils/debug.c utils/enum.c utils/identification.c \ utils/lexparser.c utils/optionsfrom.c utils/capabilities.c utils/backtrace.c \ -utils/printf_hook.c utils/settings.c +utils/settings.c if USE_DEV_HEADERS strongswan_includedir = ${dev_headers} @@ -78,7 +78,9 @@ threading/mutex.h threading/condvar.h threading/spinlock.h threading/semaphore.h threading/rwlock.h threading/rwlock_condvar.h threading/lock_profiler.h \ utils/utils.h utils/chunk.h utils/debug.h utils/enum.h utils/identification.h \ utils/lexparser.h utils/optionsfrom.h utils/capabilities.h utils/backtrace.h \ -utils/leak_detective.h utils/printf_hook.h utils/settings.h utils/integrity_checker.h +utils/leak_detective.h utils/printf_hook/printf_hook.h \ +utils/printf_hook/printf_hook_vstr.h \ +utils/settings.h utils/integrity_checker.h endif library.lo : $(top_builddir)/config.status @@ -113,9 +115,14 @@ if USE_INTEGRITY_TEST endif if USE_VSTR + libstrongswan_la_SOURCES += utils/printf_hook/printf_hook_vstr.c libstrongswan_la_LIBADD += -lvstr endif +if !USE_VSTR + libstrongswan_la_SOURCES += utils/printf_hook/printf_hook_glibc.c +endif + if USE_LIBCAP libstrongswan_la_LIBADD += -lcap endif diff --git a/src/libstrongswan/library.h b/src/libstrongswan/library.h index 560da27f9..da2798014 100644 --- a/src/libstrongswan/library.h +++ b/src/libstrongswan/library.h @@ -90,7 +90,7 @@ #endif /* make sure we include printf_hook.h and utils.h first */ -#include "utils/printf_hook.h" +#include "utils/printf_hook/printf_hook.h" #include "utils/utils.h" #include "networking/host_resolver.h" #include "networking/streams/stream_manager.h" diff --git a/src/libstrongswan/utils/enum.h b/src/libstrongswan/utils/enum.h index df8dbf8c1..a2f97d05e 100644 --- a/src/libstrongswan/utils/enum.h +++ b/src/libstrongswan/utils/enum.h @@ -22,7 +22,7 @@ #ifndef ENUM_H_ #define ENUM_H_ -#include "printf_hook.h" +#include <utils/printf_hook/printf_hook.h> typedef struct enum_name_t enum_name_t; diff --git a/src/libstrongswan/utils/printf_hook.h b/src/libstrongswan/utils/printf_hook.h deleted file mode 100644 index 1425910be..000000000 --- a/src/libstrongswan/utils/printf_hook.h +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (C) 2009 Tobias Brunner - * Copyright (C) 2006-2008 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program 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 General Public License - * for more details. - */ - -/** - * @defgroup printf_hook printf_hook - * @{ @ingroup utils - */ - -#ifndef PRINTF_HOOK_H_ -#define PRINTF_HOOK_H_ - -typedef struct printf_hook_t printf_hook_t; -typedef struct printf_hook_spec_t printf_hook_spec_t; -typedef struct printf_hook_data_t printf_hook_data_t; -typedef enum printf_hook_argtype_t printf_hook_argtype_t; - -#if !defined(USE_VSTR) && \ - !defined(HAVE_PRINTF_FUNCTION) && \ - !defined(HAVE_PRINTF_SPECIFIER) -/* assume newer glibc register_printf_specifier if none given */ -#define HAVE_PRINTF_SPECIFIER -#endif - -#if !defined(USE_VSTR) && \ - (defined(HAVE_PRINTF_FUNCTION) || defined(HAVE_PRINTF_SPECIFIER)) - -#include <stdio.h> -#include <printf.h> - -enum printf_hook_argtype_t { - PRINTF_HOOK_ARGTYPE_END = -1, - PRINTF_HOOK_ARGTYPE_INT = PA_INT, - PRINTF_HOOK_ARGTYPE_POINTER = PA_POINTER, -}; - -/** - * Data to pass to a printf hook. - */ -struct printf_hook_data_t { - - /** - * Output FILE stream - */ - FILE *stream;; -}; - -/** - * Helper macro to be used in printf hook callbacks. - */ -#define print_in_hook(data, fmt, ...) ({\ - ssize_t _written = fprintf(data->stream, fmt, ##__VA_ARGS__);\ - if (_written < 0)\ - {\ - _written = 0;\ - }\ - _written;\ -}) - -#else - -#include <vstr.h> - -enum printf_hook_argtype_t { - PRINTF_HOOK_ARGTYPE_END = VSTR_TYPE_FMT_END, - PRINTF_HOOK_ARGTYPE_INT = VSTR_TYPE_FMT_INT, - PRINTF_HOOK_ARGTYPE_POINTER = VSTR_TYPE_FMT_PTR_VOID, -}; - -/** - * Redefining printf and alike - */ -#include <stdio.h> -#include <stdarg.h> - -int vstr_wrapper_printf(const char *format, ...); -int vstr_wrapper_fprintf(FILE *stream, const char *format, ...); -int vstr_wrapper_sprintf(char *str, const char *format, ...); -int vstr_wrapper_snprintf(char *str, size_t size, const char *format, ...); -int vstr_wrapper_asprintf(char **str, const char *format, ...); - -int vstr_wrapper_vprintf(const char *format, va_list ap); -int vstr_wrapper_vfprintf(FILE *stream, const char *format, va_list ap); -int vstr_wrapper_vsprintf(char *str, const char *format, va_list ap); -int vstr_wrapper_vsnprintf(char *str, size_t size, const char *format, va_list ap); -int vstr_wrapper_vasprintf(char **str, const char *format, va_list ap); - -#ifdef printf -#undef printf -#endif -#ifdef fprintf -#undef fprintf -#endif -#ifdef sprintf -#undef sprintf -#endif -#ifdef snprintf -#undef snprintf -#endif -#ifdef asprintf -#undef asprintf -#endif -#ifdef vprintf -#undef vprintf -#endif -#ifdef vfprintf -#undef vfprintf -#endif -#ifdef vsprintf -#undef vsprintf -#endif -#ifdef vsnprintf -#undef vsnprintf -#endif -#ifdef vasprintf -#undef vasprintf -#endif - -#define printf vstr_wrapper_printf -#define fprintf vstr_wrapper_fprintf -#define sprintf vstr_wrapper_sprintf -#define snprintf vstr_wrapper_snprintf -#define asprintf vstr_wrapper_asprintf - -#define vprintf vstr_wrapper_vprintf -#define vfprintf vstr_wrapper_vfprintf -#define vsprintf vstr_wrapper_vsprintf -#define vsnprintf vstr_wrapper_vsnprintf -#define vasprintf vstr_wrapper_vasprintf - -/** - * Data to pass to a printf hook. - */ -struct printf_hook_data_t { - - /** - * Base to append printf to - */ - Vstr_base *base; - - /** - * Position in base to write to - */ - size_t pos; -}; - -/** - * Wrapper around vstr_add_vfmt(), avoids having to link all users of - * print_in_hook() against libvstr. - * - * @param base Vstr_string to add string to - * @param pos position to write to - * @param fmt format string - * @param ... arguments - * @return number of characters written - */ -size_t vstr_print_in_hook(struct Vstr_base *base, size_t pos, const char *fmt, - ...); - -/** - * Helper macro to be used in printf hook callbacks. - */ -#define print_in_hook(data, fmt, ...) ({\ - size_t _written; \ - _written = vstr_print_in_hook(data->base, data->pos, fmt, ##__VA_ARGS__);\ - data->pos += _written;\ - _written;\ -}) - -#endif - -/** - * Callback function type for printf hooks. - * - * @param data hook data, to pass to print_in_hook() - * @param spec format specifier - * @param args arguments array - * @return number of characters written - */ -typedef int (*printf_hook_function_t)(printf_hook_data_t *data, - printf_hook_spec_t *spec, - const void *const *args); - -/** - * Properties of the format specifier - */ -struct printf_hook_spec_t { - /** - * TRUE if a '#' was used in the format specifier - */ - int hash; - - /** - * TRUE if a '-' was used in the format specifier - */ - int minus; - - /** - * TRUE if a '+' was used in the format specifier - */ - int plus; - - /** - * The width as given in the format specifier. - */ - int width; -}; - -/** - * Printf handler management. - */ -struct printf_hook_t { - - /** - * Register a printf handler. - * - * @param spec printf hook format character - * @param hook hook function - * @param ... list of PRINTF_HOOK_ARGTYPE_*, MUST end with PRINTF_HOOK_ARGTYPE_END - */ - void (*add_handler)(printf_hook_t *this, char spec, - printf_hook_function_t hook, ...); - - /** - * Destroy a printf_hook instance. - */ - void (*destroy)(printf_hook_t *this); -}; - -/** - * Create a printf_hook instance. - */ -printf_hook_t *printf_hook_create(); - -#endif /** PRINTF_HOOK_H_ @}*/ diff --git a/src/libstrongswan/utils/printf_hook/printf_hook.h b/src/libstrongswan/utils/printf_hook/printf_hook.h new file mode 100644 index 000000000..5520de154 --- /dev/null +++ b/src/libstrongswan/utils/printf_hook/printf_hook.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2009 Tobias Brunner + * Copyright (C) 2006-2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program 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 General Public License + * for more details. + */ + +/** + * @defgroup printf_hook printf_hook + * @{ @ingroup utils + */ + +#ifndef PRINTF_HOOK_H_ +#define PRINTF_HOOK_H_ + +#include <stdlib.h> + +typedef struct printf_hook_t printf_hook_t; +typedef struct printf_hook_spec_t printf_hook_spec_t; +typedef struct printf_hook_data_t printf_hook_data_t; +typedef enum printf_hook_argtype_t printf_hook_argtype_t; + +#if defined(USE_VSTR) +# include "printf_hook_vstr.h" +#endif + +/** + * Argument types to pass to printf hook. + */ +enum printf_hook_argtype_t { + PRINTF_HOOK_ARGTYPE_END, + PRINTF_HOOK_ARGTYPE_INT, + PRINTF_HOOK_ARGTYPE_POINTER, +}; + +/** + * Callback function type for printf hooks. + * + * @param data hook data, to pass to print_in_hook() + * @param spec format specifier + * @param args arguments array + * @return number of characters written + */ +typedef int (*printf_hook_function_t)(printf_hook_data_t *data, + printf_hook_spec_t *spec, + const void *const *args); + +/** + * Properties of the format specifier + */ +struct printf_hook_spec_t { + + /** + * TRUE if a '#' was used in the format specifier + */ + int hash; + + /** + * TRUE if a '-' was used in the format specifier + */ + int minus; + + /** + * TRUE if a '+' was used in the format specifier + */ + int plus; + + /** + * The width as given in the format specifier. + */ + int width; +}; + +/** + * Printf handler management. + */ +struct printf_hook_t { + + /** + * Register a printf handler. + * + * @param spec printf hook format character + * @param hook hook function + * @param ... list of PRINTF_HOOK_ARGTYPE_*, MUST end with PRINTF_HOOK_ARGTYPE_END + */ + void (*add_handler)(printf_hook_t *this, char spec, + printf_hook_function_t hook, ...); + + /** + * Destroy a printf_hook instance. + */ + void (*destroy)(printf_hook_t *this); +}; + +/** + * Create a printf_hook instance. + */ +printf_hook_t *printf_hook_create(); + +/** + * Print with format string within a printf hook. + * + * @param data hook data, as passed to printf hook + * @param fmt printf format string + * @param ... arguments to format string + * @return number of characters written + */ +size_t print_in_hook(printf_hook_data_t *data, char *fmt, ...); + +#endif /** PRINTF_HOOK_H_ @}*/ diff --git a/src/libstrongswan/utils/printf_hook/printf_hook_glibc.c b/src/libstrongswan/utils/printf_hook/printf_hook_glibc.c new file mode 100644 index 000000000..8fd1aed4a --- /dev/null +++ b/src/libstrongswan/utils/printf_hook/printf_hook_glibc.c @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2009-2013 Tobias Brunner + * Copyright (C) 2006-2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program 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 General Public License + * for more details. + */ + +#include "printf_hook.h" + +#include <utils/utils.h> +#include <utils/debug.h> + +#include <printf.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> + +typedef struct private_printf_hook_t private_printf_hook_t; +typedef struct printf_hook_handler_t printf_hook_handler_t; + +/** + * private data of printf_hook + */ +struct private_printf_hook_t { + + /** + * public functions + */ + printf_hook_t public; +}; + +/** + * struct with information about a registered handler + */ +struct printf_hook_handler_t { + + /** + * callback function + */ + printf_hook_function_t hook; + + /** + * number of arguments + */ + int numargs; + + /** + * types of the arguments, PA_* + */ + int argtypes[3]; +}; + +/** + * Data to pass to a printf hook. + */ +struct printf_hook_data_t { + + /** + * Output FILE stream + */ + FILE *stream;; +}; + +/* A-Z | 6 other chars | a-z */ +static printf_hook_handler_t *printf_hooks[58]; + +#define SPEC_TO_INDEX(spec) ((int)(spec) - (int)'A') + +/** + * Glibc variant of print_in_hook() + */ +size_t print_in_hook(printf_hook_data_t *data, char *fmt, ...) +{ + ssize_t written; + va_list args; + + va_start(args, fmt); + written = vfprintf(data->stream, fmt, args); + va_end(args); + + if (written < 0) + { + written = 0; + } + return written; +} + +/** + * Printf hook print function. This is actually of type "printf_function", + * however glibc does it typedef to function, but uclibc to a pointer. + * So we redefine it here. + */ +static int custom_print(FILE *stream, const struct printf_info *info, + const void *const *args) +{ + printf_hook_spec_t spec; + printf_hook_handler_t *handler; + printf_hook_data_t data = { + .stream = stream, + }; + + handler = printf_hooks[SPEC_TO_INDEX(info->spec)]; + spec.hash = info->alt; + spec.plus = info->showsign; + spec.minus = info->left; + spec.width = info->width; + + return handler->hook(&data, &spec, args); +} + +/** + * Printf hook arginfo function, which is actually of type + * "printf_arginfo_[size_]function". + */ +static int custom_arginfo(const struct printf_info *info, size_t n, int *argtypes +#ifdef HAVE_PRINTF_SPECIFIER + , int *size +#endif + ) +{ + int i; + printf_hook_handler_t *handler; + + handler = printf_hooks[SPEC_TO_INDEX(info->spec)]; + if (handler->numargs <= n) + { + for (i = 0; i < handler->numargs; ++i) + { + argtypes[i] = handler->argtypes[i]; + } + } + /* we never set "size", as we have no user defined types */ + return handler->numargs; +} + +METHOD(printf_hook_t, add_handler, void, + private_printf_hook_t *this, char spec, + printf_hook_function_t hook, ...) +{ + int i = -1; + bool failed = FALSE; + printf_hook_handler_t *handler; + printf_hook_argtype_t argtype; + va_list args; + + if (SPEC_TO_INDEX(spec) <= -1 || + SPEC_TO_INDEX(spec) >= countof(printf_hooks)) + { + DBG1(DBG_LIB, "'%c' is not a valid printf hook specifier, " + "not registered!", spec); + return; + } + + INIT(handler, + .hook = hook, + ); + + va_start(args, hook); + while (!failed) + { + argtype = va_arg(args, printf_hook_argtype_t); + + if (argtype == PRINTF_HOOK_ARGTYPE_END) + { + break; + } + if (++i >= countof(handler->argtypes)) + { + DBG1(DBG_LIB, "Too many arguments for printf hook with " + "specifier '%c', not registered!", spec); + failed = TRUE; + break; + } + switch (argtype) + { + case PRINTF_HOOK_ARGTYPE_INT: + handler->argtypes[i] = PA_INT; + break; + case PRINTF_HOOK_ARGTYPE_POINTER: + handler->argtypes[i] = PA_POINTER; + break; + default: + DBG1(DBG_LIB, "Invalid printf hook arg type for '%c'", spec); + failed = TRUE; + break; + } + } + va_end(args); + + handler->numargs = i + 1; + if (!failed && handler->numargs > 0) + { +# ifdef HAVE_PRINTF_SPECIFIER + register_printf_specifier(spec, custom_print, custom_arginfo); +# else + register_printf_function(spec, custom_print, custom_arginfo); +# endif + printf_hooks[SPEC_TO_INDEX(spec)] = handler; + } + else + { + free(handler); + } +} + +METHOD(printf_hook_t, destroy, void, + private_printf_hook_t *this) +{ + int i; + + for (i = 0; i < countof(printf_hooks); i++) + { + free(printf_hooks[i]); + } + free(this); +} + +/* + * see header file + */ +printf_hook_t *printf_hook_create() +{ + private_printf_hook_t *this; + + INIT(this, + .public = { + .add_handler = _add_handler, + .destroy = _destroy, + }, + ); + + memset(printf_hooks, 0, sizeof(printf_hooks)); + + return &this->public; +} diff --git a/src/libstrongswan/utils/printf_hook.c b/src/libstrongswan/utils/printf_hook/printf_hook_vstr.c index aabfdc53f..f1884f119 100644 --- a/src/libstrongswan/utils/printf_hook.c +++ b/src/libstrongswan/utils/printf_hook/printf_hook_vstr.c @@ -16,13 +16,14 @@ #include "printf_hook.h" -#include "utils.h" -#include "debug.h" +#include <utils/utils.h> +#include <utils/debug.h> +#include <threading/thread_value.h> -#include <stdio.h> -#include <stdarg.h> +#include <vstr.h> #include <string.h> -#include <sys/uio.h> +#include <unistd.h> +#include <errno.h> typedef struct private_printf_hook_t private_printf_hook_t; typedef struct printf_hook_handler_t printf_hook_handler_t; @@ -57,78 +58,36 @@ struct printf_hook_handler_t { int numargs; /** - * types of the arguments + * types of the arguments, VSTR_TYPE_FMT_* */ int argtypes[ARGS_MAX]; -#ifdef USE_VSTR /** * name required for Vstr */ char *name; -#endif }; -/* A-Z | 6 other chars | a-z */ -#define NUM_HANDLERS 58 -static printf_hook_handler_t *printf_hooks[NUM_HANDLERS]; - -#define SPEC_TO_INDEX(spec) ((int)(spec) - (int)'A') -#define IS_VALID_SPEC(spec) (SPEC_TO_INDEX(spec) > -1 && SPEC_TO_INDEX(spec) < NUM_HANDLERS) - -#if !defined(USE_VSTR) && \ - (defined(HAVE_PRINTF_FUNCTION) || defined(HAVE_PRINTF_SPECIFIER)) - /** - * Printf hook print function. This is actually of type "printf_function", - * however glibc does it typedef to function, but uclibc to a pointer. - * So we redefine it here. + * Data to pass to a printf hook. */ -static int custom_print(FILE *stream, const struct printf_info *info, - const void *const *args) -{ - printf_hook_spec_t spec; - printf_hook_handler_t *handler = printf_hooks[SPEC_TO_INDEX(info->spec)]; - printf_hook_data_t data = { - .stream = stream, - }; - - spec.hash = info->alt; - spec.plus = info->showsign; - spec.minus = info->left; - spec.width = info->width; - - return handler->hook(&data, &spec, args); -} +struct printf_hook_data_t { -/** - * Printf hook arginfo function, which is actually of type - * "printf_arginfo_[size_]function". - */ -static int custom_arginfo(const struct printf_info *info, size_t n, int *argtypes -#ifdef HAVE_PRINTF_SPECIFIER - , int *size -#endif - ) -{ - int i; - printf_hook_handler_t *handler = printf_hooks[SPEC_TO_INDEX(info->spec)]; + /** + * Base to append printf to + */ + Vstr_base *base; - if (handler->numargs <= n) - { - for (i = 0; i < handler->numargs; ++i) - { - argtypes[i] = handler->argtypes[i]; - } - } - /* we never set "size", as we have no user defined types */ - return handler->numargs; -} + /** + * Position in base to write to + */ + size_t pos; +}; -#else +/* A-Z | 6 other chars | a-z */ +static printf_hook_handler_t *printf_hooks[58]; -#include <errno.h> -#include <unistd.h> /* for STDOUT_FILENO */ +#define SPEC_TO_INDEX(spec) ((int)(spec) - (int)'A') /** * These are used below, whenever the public wrapper functions are called before @@ -139,6 +98,22 @@ static int custom_arginfo(const struct printf_info *info, size_t n, int *argtype #undef vsnprintf /** + * Vstr variant of print_in_hook() + */ +size_t print_in_hook(printf_hook_data_t *data, char *fmt, ...) +{ + size_t written; + va_list args; + + va_start(args, fmt); + written = vstr_add_vfmt(data->base, data->pos, fmt, args); + va_end(args); + + data->pos += written; + return written; +} + +/** * Vstr custom format specifier callback function. */ static int custom_fmt_cb(Vstr_base *base, size_t pos, Vstr_fmt_spec *fmt_spec) @@ -146,20 +121,21 @@ static int custom_fmt_cb(Vstr_base *base, size_t pos, Vstr_fmt_spec *fmt_spec) int i; const void *args[ARGS_MAX]; printf_hook_spec_t spec; - printf_hook_handler_t *handler = printf_hooks[SPEC_TO_INDEX(fmt_spec->name[0])]; + printf_hook_handler_t *handler; printf_hook_data_t data = { .base = base, .pos = pos, }; + handler = printf_hooks[SPEC_TO_INDEX(fmt_spec->name[0])]; for (i = 0; i < handler->numargs; i++) { - switch(handler->argtypes[i]) + switch (handler->argtypes[i]) { - case PRINTF_HOOK_ARGTYPE_INT: + case VSTR_TYPE_FMT_INT: args[i] = VSTR_FMT_CB_ARG_PTR(fmt_spec, i); break; - case PRINTF_HOOK_ARGTYPE_POINTER: + case VSTR_TYPE_FMT_PTR_VOID: args[i] = &VSTR_FMT_CB_ARG_PTR(fmt_spec, i); break; } @@ -171,6 +147,7 @@ static int custom_fmt_cb(Vstr_base *base, size_t pos, Vstr_fmt_spec *fmt_spec) spec.width = fmt_spec->fmt_field_width; handler->hook(&data, &spec, args); + return 1; } @@ -179,8 +156,10 @@ static int custom_fmt_cb(Vstr_base *base, size_t pos, Vstr_fmt_spec *fmt_spec) */ static void vstr_fmt_add_handler(Vstr_conf *conf, printf_hook_handler_t *handler) { - int *at = handler->argtypes; - switch(handler->numargs) + int *at; + + at = handler->argtypes; + switch (handler->numargs) { case 1: vstr_fmt_add(conf, handler->name, custom_fmt_cb, at[0], @@ -198,34 +177,41 @@ static void vstr_fmt_add_handler(Vstr_conf *conf, printf_hook_handler_t *handler } /** - * Management of thread-specific Vstr_conf objects + * Thread specific vstr config */ -#include <threading/thread_value.h> - static thread_value_t *vstr_conf = NULL; +/** + * Create vstr config for current thread + */ static Vstr_conf *create_vstr_conf() { + Vstr_conf *conf; int i; - Vstr_conf *conf = vstr_make_conf(); + + conf = vstr_make_conf(); vstr_cntl_conf(conf, VSTR_CNTL_CONF_SET_FMT_CHAR_ESC, '%'); vstr_cntl_conf(conf, VSTR_CNTL_CONF_SET_TYPE_GRPALLOC_CACHE, VSTR_TYPE_CNTL_CONF_GRPALLOC_CSTR); vstr_cntl_conf(conf, VSTR_CNTL_CONF_SET_NUM_BUF_SZ, PRINTF_BUF_LEN); - for (i = 0; i < NUM_HANDLERS; ++i) + + for (i = 0; i < countof(printf_hooks); i++) { - printf_hook_handler_t *handler = printf_hooks[i]; - if (handler) + if (printf_hooks[i]) { - vstr_fmt_add_handler(conf, handler); + vstr_fmt_add_handler(conf, printf_hooks[i]); } } return conf; } +/** + * Get vstr config of current thread + */ static inline Vstr_conf *get_vstr_conf() { Vstr_conf *conf = NULL; + if (vstr_conf) { conf = (Vstr_conf*)vstr_conf->get(vstr_conf); @@ -239,21 +225,6 @@ static inline Vstr_conf *get_vstr_conf() } /** - * Described in header - */ -size_t vstr_print_in_hook(struct Vstr_base *base, size_t pos, const char *fmt, - ...) -{ - va_list args; - int written; - - va_start(args, fmt); - written = vstr_add_vfmt(base, pos, fmt, args); - va_end(args); - return written; -} - -/** * Wrapper functions for printf and alike */ int vstr_wrapper_printf(const char *format, ...) @@ -265,6 +236,7 @@ int vstr_wrapper_printf(const char *format, ...) va_end(args); return written; } + int vstr_wrapper_fprintf(FILE *stream, const char *format, ...) { int written; @@ -274,6 +246,7 @@ int vstr_wrapper_fprintf(FILE *stream, const char *format, ...) va_end(args); return written; } + int vstr_wrapper_sprintf(char *str, const char *format, ...) { int written; @@ -283,6 +256,7 @@ int vstr_wrapper_sprintf(char *str, const char *format, ...) va_end(args); return written; } + int vstr_wrapper_snprintf(char *str, size_t size, const char *format, ...) { int written; @@ -292,6 +266,7 @@ int vstr_wrapper_snprintf(char *str, size_t size, const char *format, ...) va_end(args); return written; } + int vstr_wrapper_asprintf(char **str, const char *format, ...) { int written; @@ -301,13 +276,16 @@ int vstr_wrapper_asprintf(char **str, const char *format, ...) va_end(args); return written; } + static inline int vstr_wrapper_vprintf_internal(Vstr_conf *conf, FILE *stream, const char *format, va_list args) { struct iovec *iov; int iovcnt, written = 0; - Vstr_base *s = vstr_make_base(conf); + Vstr_base *s; + + s = vstr_make_base(conf); vstr_add_vfmt(s, 0, format, args); if (vstr_export_iovec_ptr_all(s, &iov, &iovcnt)) { @@ -323,33 +301,43 @@ static inline int vstr_wrapper_vprintf_internal(Vstr_conf *conf, FILE *stream, vstr_free_base(s); return written; } + int vstr_wrapper_vprintf(const char *format, va_list args) { - Vstr_conf *conf = get_vstr_conf(); + Vstr_conf *conf; + + conf = get_vstr_conf(); if (conf) { return vstr_wrapper_vprintf_internal(conf, stdout, format, args); } return vprintf(format, args); } + int vstr_wrapper_vfprintf(FILE *stream, const char *format, va_list args) { - Vstr_conf *conf = get_vstr_conf(); + Vstr_conf *conf; + + conf = get_vstr_conf(); if (conf) { return vstr_wrapper_vprintf_internal(conf, stream, format, args); } return vfprintf(stream, format, args); } + static inline int vstr_wrapper_vsnprintf_internal(char *str, size_t size, const char *format, va_list args) { - Vstr_conf *conf = get_vstr_conf(); + Vstr_conf *conf; + Vstr_base *s; + int written; + + conf = get_vstr_conf(); if (conf) { - int written; - Vstr_base *s = vstr_make_base(conf); + s = vstr_make_base(conf); vstr_add_vfmt(s, 0, format, args); written = s->len; vstr_export_cstr_buf(s, 1, s->len, str, (size > 0) ? size : s->len + 1); @@ -358,19 +346,27 @@ static inline int vstr_wrapper_vsnprintf_internal(char *str, size_t size, } return vsnprintf(str, size, format, args); } + int vstr_wrapper_vsprintf(char *str, const char *format, va_list args) { return vstr_wrapper_vsnprintf_internal(str, 0, format, args); } + int vstr_wrapper_vsnprintf(char *str, size_t size, const char *format, va_list args) { - return (size > 0) ? vstr_wrapper_vsnprintf_internal(str, size, format, args) : 0; + if (size > 0) + { + return vstr_wrapper_vsnprintf_internal(str, size, format, args); + } + return 0; } + int vstr_wrapper_vasprintf(char **str, const char *format, va_list args) { size_t len = 100; int written; + *str = malloc(len); while (TRUE) { @@ -387,60 +383,68 @@ int vstr_wrapper_vasprintf(char **str, const char *format, va_list args) } return written; } -#endif METHOD(printf_hook_t, add_handler, void, - private_printf_hook_t *this, char spec, - printf_hook_function_t hook, ...) + private_printf_hook_t *this, char spec, printf_hook_function_t hook, ...) { int i = -1; + bool failed = FALSE; printf_hook_handler_t *handler; printf_hook_argtype_t argtype; va_list args; - if (!IS_VALID_SPEC(spec)) + if (SPEC_TO_INDEX(spec) <= -1 || + SPEC_TO_INDEX(spec) >= countof(printf_hooks)) { DBG1(DBG_LIB, "'%c' is not a valid printf hook specifier, " "not registered!", spec); return; } - handler = malloc_thing(printf_hook_handler_t); - handler->hook = hook; + INIT(handler, + .hook = hook, + ); va_start(args, hook); - while ((argtype = va_arg(args, printf_hook_argtype_t)) != PRINTF_HOOK_ARGTYPE_END) + while (!failed) { + argtype = va_arg(args, printf_hook_argtype_t); + if (argtype == PRINTF_HOOK_ARGTYPE_END) + { + break; + } if (++i >= ARGS_MAX) { DBG1(DBG_LIB, "Too many arguments for printf hook with " "specifier '%c', not registered!", spec); - va_end(args); - free(handler); - return; + failed = TRUE; + break; + } + switch (argtype) + { + case PRINTF_HOOK_ARGTYPE_INT: + handler->argtypes[i] = VSTR_TYPE_FMT_INT; + break; + case PRINTF_HOOK_ARGTYPE_POINTER: + handler->argtypes[i] = VSTR_TYPE_FMT_PTR_VOID; + break; + default: + DBG1(DBG_LIB, "Invalid printf hook arg type for '%c'", spec); + failed = TRUE; + break; } - handler->argtypes[i] = argtype; } va_end(args); handler->numargs = i + 1; - if (handler->numargs > 0) + if (!failed && handler->numargs > 0) { -#if !defined(USE_VSTR) && \ - (defined(HAVE_PRINTF_FUNCTION) || defined(HAVE_PRINTF_SPECIFIER)) -# ifdef HAVE_PRINTF_SPECIFIER - register_printf_specifier(spec, custom_print, custom_arginfo); -# else - register_printf_function(spec, custom_print, custom_arginfo); -# endif -#else Vstr_conf *conf = get_vstr_conf(); handler->name = malloc(2); handler->name[0] = spec; handler->name[1] = '\0'; vstr_fmt_add_handler(conf, handler); -#endif printf_hooks[SPEC_TO_INDEX(spec)] = handler; } else @@ -453,29 +457,25 @@ METHOD(printf_hook_t, destroy, void, private_printf_hook_t *this) { int i; -#ifdef USE_VSTR - Vstr_conf *conf = get_vstr_conf(); -#endif + Vstr_conf *conf; + printf_hook_handler_t *handler; - for (i = 0; i < NUM_HANDLERS; ++i) + conf = get_vstr_conf(); + for (i = 0; i < countof(printf_hooks); ++i) { - printf_hook_handler_t *handler = printf_hooks[i]; + handler = printf_hooks[i]; if (handler) { -#ifdef USE_VSTR vstr_fmt_del(conf, handler->name); free(handler->name); -#endif free(handler); } } -#ifdef USE_VSTR /* freeing the Vstr_conf of the main thread */ vstr_conf->destroy(vstr_conf); vstr_conf = NULL; vstr_exit(); -#endif free(this); } @@ -495,7 +495,6 @@ printf_hook_t *printf_hook_create() memset(printf_hooks, 0, sizeof(printf_hooks)); -#ifdef USE_VSTR if (!vstr_init()) { DBG1(DBG_LIB, "failed to initialize Vstr library!"); @@ -503,8 +502,6 @@ printf_hook_t *printf_hook_create() return NULL; } vstr_conf = thread_value_create((thread_cleanup_t)vstr_free_conf); -#endif return &this->public; } - diff --git a/src/libstrongswan/utils/printf_hook/printf_hook_vstr.h b/src/libstrongswan/utils/printf_hook/printf_hook_vstr.h new file mode 100644 index 000000000..2f9ee5983 --- /dev/null +++ b/src/libstrongswan/utils/printf_hook/printf_hook_vstr.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2009 Tobias Brunner + * Copyright (C) 2006-2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program 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 General Public License + * for more details. + */ + +/** + * @defgroup printf_hook_vstr printf_hook_vstr + * @{ @ingroup utils + */ + +#ifndef PRINTF_HOOK_VSTR_H_ +#define PRINTF_HOOK_VSTR_H_ + +#include <stdarg.h> +#include <stdio.h> + +int vstr_wrapper_printf(const char *format, ...); +int vstr_wrapper_fprintf(FILE *stream, const char *format, ...); +int vstr_wrapper_sprintf(char *str, const char *format, ...); +int vstr_wrapper_snprintf(char *str, size_t size, const char *format, ...); +int vstr_wrapper_asprintf(char **str, const char *format, ...); + +int vstr_wrapper_vprintf(const char *format, va_list ap); +int vstr_wrapper_vfprintf(FILE *stream, const char *format, va_list ap); +int vstr_wrapper_vsprintf(char *str, const char *format, va_list ap); +int vstr_wrapper_vsnprintf(char *str, size_t size, const char *format, va_list ap); +int vstr_wrapper_vasprintf(char **str, const char *format, va_list ap); + +#ifdef printf +#undef printf +#endif +#ifdef fprintf +#undef fprintf +#endif +#ifdef sprintf +#undef sprintf +#endif +#ifdef snprintf +#undef snprintf +#endif +#ifdef asprintf +#undef asprintf +#endif +#ifdef vprintf +#undef vprintf +#endif +#ifdef vfprintf +#undef vfprintf +#endif +#ifdef vsprintf +#undef vsprintf +#endif +#ifdef vsnprintf +#undef vsnprintf +#endif +#ifdef vasprintf +#undef vasprintf +#endif + +#define printf vstr_wrapper_printf +#define fprintf vstr_wrapper_fprintf +#define sprintf vstr_wrapper_sprintf +#define snprintf vstr_wrapper_snprintf +#define asprintf vstr_wrapper_asprintf + +#define vprintf vstr_wrapper_vprintf +#define vfprintf vstr_wrapper_vfprintf +#define vsprintf vstr_wrapper_vsprintf +#define vsnprintf vstr_wrapper_vsnprintf +#define vasprintf vstr_wrapper_vasprintf + +#endif /** PRINTF_HOOK_VSTR_H_ @}*/ |