Merge branch 'printf-hook'
Adds a custom printf hook implementation as a fallback if neither the glibc style hooks nor vstr is available. This can avoid the Vstr dependency on some systems at the cost of slower and less complete printf functions.
This commit is contained in:
+7
-1
@@ -624,7 +624,7 @@ AC_CHECK_FUNC(
|
||||
[AC_DEFINE([HAVE_PRINTF_FUNCTION], [], [have register_printf_function()])],
|
||||
[
|
||||
AC_MSG_NOTICE([printf does not support custom format specifiers!])
|
||||
vstr=true
|
||||
builtin_printf=true
|
||||
]
|
||||
)]
|
||||
)
|
||||
@@ -632,6 +632,11 @@ AC_CHECK_FUNC(
|
||||
if test x$vstr = xtrue; then
|
||||
AC_CHECK_LIB([vstr],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([Vstr string library not found])],[])
|
||||
AC_DEFINE([USE_VSTR], [], [use vstring library for printf hooks])
|
||||
builtin_printf=false
|
||||
fi
|
||||
|
||||
if test x$builtin_printf = xtrue; then
|
||||
AC_DEFINE([USE_BUILTIN_PRINTF], [], [using builtin printf for printf hooks])
|
||||
fi
|
||||
|
||||
if test x$gmp = xtrue; then
|
||||
@@ -1278,6 +1283,7 @@ AM_CONDITIONAL(USE_FILE_CONFIG, test x$stroke = xtrue)
|
||||
AM_CONDITIONAL(USE_IPSEC_SCRIPT, test x$stroke = xtrue -o x$tools = xtrue -o x$conftest = xtrue)
|
||||
AM_CONDITIONAL(USE_LIBCAP, test x$capabilities = xlibcap)
|
||||
AM_CONDITIONAL(USE_VSTR, test x$vstr = xtrue)
|
||||
AM_CONDITIONAL(USE_BUILTIN_PRINTF, test x$builtin_printf = xtrue)
|
||||
AM_CONDITIONAL(USE_SIMAKA, test x$simaka = xtrue)
|
||||
AM_CONDITIONAL(USE_TLS, test x$tls = xtrue)
|
||||
AM_CONDITIONAL(USE_RADIUS, test x$radius = xtrue)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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/printf_hook/printf_hook_builtin.h \
|
||||
utils/settings.h utils/integrity_checker.h
|
||||
endif
|
||||
|
||||
library.lo : $(top_builddir)/config.status
|
||||
@@ -113,9 +115,21 @@ 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_BUILTIN_PRINTF
|
||||
libstrongswan_la_SOURCES += utils/printf_hook/printf_hook_builtin.c
|
||||
libstrongswan_la_LIBADD += -lm
|
||||
endif
|
||||
|
||||
if !USE_BUILTIN_PRINTF
|
||||
if !USE_VSTR
|
||||
libstrongswan_la_SOURCES += utils/printf_hook/printf_hook_glibc.c
|
||||
endif
|
||||
endif
|
||||
|
||||
if USE_LIBCAP
|
||||
libstrongswan_la_LIBADD += -lcap
|
||||
endif
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -7,7 +7,7 @@ test_runner_SOURCES = \
|
||||
test_linked_list.c test_enumerator.c test_linked_list_enumerator.c \
|
||||
test_bio_reader.c test_bio_writer.c test_chunk.c test_enum.c test_hashtable.c \
|
||||
test_identification.c test_threading.c test_utils.c test_vectors.c \
|
||||
test_array.c test_ecdsa.c test_rsa.c test_host.c
|
||||
test_array.c test_ecdsa.c test_rsa.c test_host.c test_printf.c
|
||||
|
||||
test_runner_CFLAGS = \
|
||||
-I$(top_srcdir)/src/libstrongswan \
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Martin Willi
|
||||
* Copyright (C) 2013 revosec AG
|
||||
*
|
||||
* 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 "test_suite.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
|
||||
static void verify(char *expected, char *format, ...)
|
||||
{
|
||||
FILE *mem;
|
||||
char buf[128];
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
vsnprintf(buf, sizeof(buf), format, args);
|
||||
ck_assert_str_eq(expected, buf);
|
||||
va_end(args);
|
||||
|
||||
mem = fmemopen(buf, sizeof(buf), "w");
|
||||
va_start(args, format);
|
||||
vfprintf(mem, format, args);
|
||||
va_end(args);
|
||||
fclose(mem);
|
||||
ck_assert_str_eq(expected, buf);
|
||||
}
|
||||
|
||||
START_TEST(test_printf_strings)
|
||||
{
|
||||
verify("a bc def", "%s %s %s", "a", "bc", "def");
|
||||
verify("asd", "%.3s", "asdfg");
|
||||
verify("asdf", "%.*s", (int)4, "asdfg");
|
||||
verify(" asdf", "%6s", "asdf");
|
||||
verify(" asdf", "%+6s", "asdf");
|
||||
verify("asdf ", "%-6s", "asdf");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_printf_err)
|
||||
{
|
||||
errno = EINVAL;
|
||||
verify((char*)strerror(errno), "%m");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_printf_unsigned)
|
||||
{
|
||||
verify("1 23 456", "%u %lu %llu", 1, (u_long)23, (u_int64_t)456);
|
||||
verify("65535 255", "%hu %hhu", 0x1ffff, 0x1ff);
|
||||
verify("123456789", "%zu", (size_t)123456789);
|
||||
verify(" 12", "%5u", 12);
|
||||
verify("12 ", "%-5u", 12);
|
||||
verify("0012", "%04u", 12);
|
||||
verify("0012", "%.4u", 12);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_printf_signed)
|
||||
{
|
||||
verify("-1 -23 -456", "%d %ld %lld", -1, (long)-23, (int64_t)-456);
|
||||
verify("-1 -1", "%hd %hhd", 0x1ffff, 0x1ff);
|
||||
verify("123456789", "%zd", (ssize_t)123456789);
|
||||
verify(" -12", "%5d", -12);
|
||||
verify("-12 ", "%-5d", -12);
|
||||
verify("-012", "%04d", -12);
|
||||
verify("-0012", "%.4d", -12);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_printf_hex)
|
||||
{
|
||||
verify("1 23 456", "%x %lx %llx", 1, (u_long)0x23, (u_int64_t)0x456);
|
||||
verify("12abcdef 12ABCDEF", "%x %X", 0x12ABCDEF, 0x12ABCDEF);
|
||||
verify("ffff ff", "%hx %hhx", 0x1ffff, 0x1ff);
|
||||
verify("23456789", "%zx", (size_t)0x23456789);
|
||||
verify(" ab", "%5x", 0xab);
|
||||
verify("ab ", "%-5x", 0xab);
|
||||
verify("00ab", "%04x", 0xab);
|
||||
verify("00ab", "%.4x", 0xab);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_printf_float)
|
||||
{
|
||||
verify("0.000000", "%f", 0.0);
|
||||
verify("1.000000", "%f", 1.0);
|
||||
verify("12345.1", "%.1f", 12345.123);
|
||||
verify("1", "%.0f", 1.0);
|
||||
verify("1.3", "%.1f", 1.346789);
|
||||
verify("1.23", "%.2f", 1.23456789);
|
||||
verify("1.123", "%.3f", 1.123456789);
|
||||
verify("1.0123", "%.4f", 1.0123456789);
|
||||
|
||||
verify("-1.000000", "%f", -1.0);
|
||||
verify("-12345.1", "%.1f", -12345.123);
|
||||
verify("-1", "%.0f", -1.0);
|
||||
verify("-1.3", "%.1f", -1.3456789);
|
||||
verify("-1.23", "%.2f", -1.23456789);
|
||||
verify("-1.123", "%.3f", -1.123456789);
|
||||
verify("-1.0123", "%.4f", -1.0123456789);
|
||||
|
||||
verify(" 1.2", "%5.1f", 1.234);
|
||||
verify("001.2", "%05.1f", 1.234);
|
||||
verify("1.2 ", "%-5.1f", 1.234);
|
||||
|
||||
verify("12346", "%.0f", 12345.6789);
|
||||
verify("2", "%.0f", 1.5);
|
||||
verify("1", "%.0f", 1.49);
|
||||
verify("1.2", "%.1f", 1.151);
|
||||
verify("1.1", "%.1f", 1.149);
|
||||
verify("1.13", "%.2f", 1.1251);
|
||||
verify("1.12", "%.2f", 1.1249);
|
||||
verify("1.124", "%.3f", 1.12351);
|
||||
verify("1.123", "%.3f", 1.12349);
|
||||
|
||||
verify("-12346", "%.0f", -12345.6789);
|
||||
verify("-2", "%.0f", -1.51);
|
||||
verify("-1", "%.0f", -1.49);
|
||||
verify("-1.2", "%.1f", -1.151);
|
||||
verify("-1.1", "%.1f", -1.149);
|
||||
verify("-1.13", "%.2f", -1.1251);
|
||||
verify("-1.12", "%.2f", -1.1249);
|
||||
verify("-1.124", "%.3f", -1.12351);
|
||||
verify("-1.123", "%.3f", -1.12349);
|
||||
|
||||
#ifdef NAN
|
||||
verify("nan", "%.3f", NAN);
|
||||
verify(" nan", "%5.3f", NAN);
|
||||
verify("NAN", "%.3F", NAN);
|
||||
verify("NAN ", "%-5.3F", NAN);
|
||||
#endif
|
||||
#ifdef INFINITY
|
||||
verify("inf", "%.3f", INFINITY);
|
||||
verify("-inf", "%.4f", -INFINITY);
|
||||
verify("INF", "%.3F", INFINITY);
|
||||
verify("-INF", "%.4F", -INFINITY);
|
||||
#endif
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite *printf_suite_create()
|
||||
{
|
||||
Suite *s;
|
||||
TCase *tc;
|
||||
|
||||
s = suite_create("printf");
|
||||
|
||||
tc = tcase_create("strings");
|
||||
tcase_add_test(tc, test_printf_strings);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("err");
|
||||
tcase_add_test(tc, test_printf_err);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("unsiged");
|
||||
tcase_add_test(tc, test_printf_unsigned);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("siged");
|
||||
tcase_add_test(tc, test_printf_signed);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("hex");
|
||||
tcase_add_test(tc, test_printf_hex);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("float");
|
||||
tcase_add_test(tc, test_printf_float);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
return s;
|
||||
}
|
||||
@@ -84,6 +84,7 @@ int main()
|
||||
srunner_add_suite(sr, utils_suite_create());
|
||||
srunner_add_suite(sr, host_suite_create());
|
||||
srunner_add_suite(sr, vectors_suite_create());
|
||||
srunner_add_suite(sr, printf_suite_create());
|
||||
if (lib->plugins->has_feature(lib->plugins,
|
||||
PLUGIN_DEPENDS(PRIVKEY_GEN, KEY_RSA)))
|
||||
{
|
||||
|
||||
@@ -34,5 +34,6 @@ Suite *vectors_suite_create();
|
||||
Suite *ecdsa_suite_create();
|
||||
Suite *rsa_suite_create();
|
||||
Suite *host_suite_create();
|
||||
Suite *printf_suite_create();
|
||||
|
||||
#endif /** TEST_RUNNER_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;
|
||||
|
||||
|
||||
@@ -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_ @}*/
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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"
|
||||
#elif defined(USE_BUILTIN_PRINTF)
|
||||
# include "printf_hook_builtin.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_ @}*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Martin Willi
|
||||
* Copyright (C) 2013 revosec AG
|
||||
*
|
||||
* 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_builtin printf_hook_builtin
|
||||
* @{ @ingroup utils
|
||||
*/
|
||||
|
||||
#ifndef PRINTF_HOOK_BUILTIN_H_
|
||||
#define PRINTF_HOOK_BUILTIN_H_
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int builtin_printf(const char *format, ...);
|
||||
int builtin_fprintf(FILE *stream, const char *format, ...);
|
||||
int builtin_sprintf(char *str, const char *format, ...);
|
||||
int builtin_snprintf(char *str, size_t size, const char *format, ...);
|
||||
int builtin_asprintf(char **str, const char *format, ...);
|
||||
|
||||
int builtin_vprintf(const char *format, va_list ap);
|
||||
int builtin_vfprintf(FILE *stream, const char *format, va_list ap);
|
||||
int builtin_vsprintf(char *str, const char *format, va_list ap);
|
||||
int builtin_vsnprintf(char *str, size_t size, const char *format, va_list ap);
|
||||
int builtin_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 builtin_printf
|
||||
#define fprintf builtin_fprintf
|
||||
#define sprintf builtin_sprintf
|
||||
#define snprintf builtin_snprintf
|
||||
#define asprintf builtin_asprintf
|
||||
|
||||
#define vprintf builtin_vprintf
|
||||
#define vfprintf builtin_vfprintf
|
||||
#define vsprintf builtin_vsprintf
|
||||
#define vsnprintf builtin_vsnprintf
|
||||
#define vasprintf builtin_vasprintf
|
||||
|
||||
#endif /** PRINTF_HOOK_BUILTIN_H_ @}*/
|
||||
@@ -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;
|
||||
}
|
||||
+131
-134
@@ -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
|
||||
};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
|
||||
/* A-Z | 6 other chars | a-z */
|
||||
#define NUM_HANDLERS 58
|
||||
static printf_hook_handler_t *printf_hooks[NUM_HANDLERS];
|
||||
static printf_hook_handler_t *printf_hooks[58];
|
||||
|
||||
#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.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h> /* for STDOUT_FILENO */
|
||||
|
||||
/**
|
||||
* These are used below, whenever the public wrapper functions are called before
|
||||
@@ -138,6 +97,22 @@ static int custom_arginfo(const struct printf_info *info, size_t n, int *argtype
|
||||
#undef vfprintf
|
||||
#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.
|
||||
*/
|
||||
@@ -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);
|
||||
@@ -238,21 +224,6 @@ static inline Vstr_conf *get_vstr_conf()
|
||||
return 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
|
||||
*/
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ @}*/
|
||||
Reference in New Issue
Block a user