printf-hook: Move glibc/vstr printf hook backends to separate files
This commit is contained in:
@@ -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 \
|
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/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/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
|
# 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 \
|
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/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/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
|
if USE_DEV_HEADERS
|
||||||
strongswan_includedir = ${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 \
|
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/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/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
|
endif
|
||||||
|
|
||||||
library.lo : $(top_builddir)/config.status
|
library.lo : $(top_builddir)/config.status
|
||||||
@@ -113,9 +115,14 @@ if USE_INTEGRITY_TEST
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
if USE_VSTR
|
if USE_VSTR
|
||||||
|
libstrongswan_la_SOURCES += utils/printf_hook/printf_hook_vstr.c
|
||||||
libstrongswan_la_LIBADD += -lvstr
|
libstrongswan_la_LIBADD += -lvstr
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if !USE_VSTR
|
||||||
|
libstrongswan_la_SOURCES += utils/printf_hook/printf_hook_glibc.c
|
||||||
|
endif
|
||||||
|
|
||||||
if USE_LIBCAP
|
if USE_LIBCAP
|
||||||
libstrongswan_la_LIBADD += -lcap
|
libstrongswan_la_LIBADD += -lcap
|
||||||
endif
|
endif
|
||||||
|
|||||||
@@ -90,7 +90,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* make sure we include printf_hook.h and utils.h first */
|
/* 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 "utils/utils.h"
|
||||||
#include "networking/host_resolver.h"
|
#include "networking/host_resolver.h"
|
||||||
#include "networking/streams/stream_manager.h"
|
#include "networking/streams/stream_manager.h"
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
#ifndef ENUM_H_
|
#ifndef ENUM_H_
|
||||||
#define ENUM_H_
|
#define ENUM_H_
|
||||||
|
|
||||||
#include "printf_hook.h"
|
#include <utils/printf_hook/printf_hook.h>
|
||||||
|
|
||||||
typedef struct enum_name_t enum_name_t;
|
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,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_ @}*/
|
||||||
@@ -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 "printf_hook.h"
|
||||||
|
|
||||||
#include "utils.h"
|
#include <utils/utils.h>
|
||||||
#include "debug.h"
|
#include <utils/debug.h>
|
||||||
|
#include <threading/thread_value.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <vstr.h>
|
||||||
#include <stdarg.h>
|
|
||||||
#include <string.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 private_printf_hook_t private_printf_hook_t;
|
||||||
typedef struct printf_hook_handler_t printf_hook_handler_t;
|
typedef struct printf_hook_handler_t printf_hook_handler_t;
|
||||||
@@ -57,78 +58,36 @@ struct printf_hook_handler_t {
|
|||||||
int numargs;
|
int numargs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* types of the arguments
|
* types of the arguments, VSTR_TYPE_FMT_*
|
||||||
*/
|
*/
|
||||||
int argtypes[ARGS_MAX];
|
int argtypes[ARGS_MAX];
|
||||||
|
|
||||||
#ifdef USE_VSTR
|
|
||||||
/**
|
/**
|
||||||
* name required for Vstr
|
* name required for Vstr
|
||||||
*/
|
*/
|
||||||
char *name;
|
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 */
|
/* A-Z | 6 other chars | a-z */
|
||||||
#define NUM_HANDLERS 58
|
static printf_hook_handler_t *printf_hooks[58];
|
||||||
static printf_hook_handler_t *printf_hooks[NUM_HANDLERS];
|
|
||||||
|
|
||||||
#define SPEC_TO_INDEX(spec) ((int)(spec) - (int)'A')
|
#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
|
* 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 vfprintf
|
||||||
#undef vsnprintf
|
#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.
|
* 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;
|
int i;
|
||||||
const void *args[ARGS_MAX];
|
const void *args[ARGS_MAX];
|
||||||
printf_hook_spec_t spec;
|
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 = {
|
printf_hook_data_t data = {
|
||||||
.base = base,
|
.base = base,
|
||||||
.pos = pos,
|
.pos = pos,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handler = printf_hooks[SPEC_TO_INDEX(fmt_spec->name[0])];
|
||||||
for (i = 0; i < handler->numargs; i++)
|
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);
|
args[i] = VSTR_FMT_CB_ARG_PTR(fmt_spec, i);
|
||||||
break;
|
break;
|
||||||
case PRINTF_HOOK_ARGTYPE_POINTER:
|
case VSTR_TYPE_FMT_PTR_VOID:
|
||||||
args[i] = &VSTR_FMT_CB_ARG_PTR(fmt_spec, i);
|
args[i] = &VSTR_FMT_CB_ARG_PTR(fmt_spec, i);
|
||||||
break;
|
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;
|
spec.width = fmt_spec->fmt_field_width;
|
||||||
|
|
||||||
handler->hook(&data, &spec, args);
|
handler->hook(&data, &spec, args);
|
||||||
|
|
||||||
return 1;
|
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)
|
static void vstr_fmt_add_handler(Vstr_conf *conf, printf_hook_handler_t *handler)
|
||||||
{
|
{
|
||||||
int *at = handler->argtypes;
|
int *at;
|
||||||
switch(handler->numargs)
|
|
||||||
|
at = handler->argtypes;
|
||||||
|
switch (handler->numargs)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
vstr_fmt_add(conf, handler->name, custom_fmt_cb, at[0],
|
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;
|
static thread_value_t *vstr_conf = NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create vstr config for current thread
|
||||||
|
*/
|
||||||
static Vstr_conf *create_vstr_conf()
|
static Vstr_conf *create_vstr_conf()
|
||||||
{
|
{
|
||||||
|
Vstr_conf *conf;
|
||||||
int i;
|
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_FMT_CHAR_ESC, '%');
|
||||||
vstr_cntl_conf(conf, VSTR_CNTL_CONF_SET_TYPE_GRPALLOC_CACHE,
|
vstr_cntl_conf(conf, VSTR_CNTL_CONF_SET_TYPE_GRPALLOC_CACHE,
|
||||||
VSTR_TYPE_CNTL_CONF_GRPALLOC_CSTR);
|
VSTR_TYPE_CNTL_CONF_GRPALLOC_CSTR);
|
||||||
vstr_cntl_conf(conf, VSTR_CNTL_CONF_SET_NUM_BUF_SZ, PRINTF_BUF_LEN);
|
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 (printf_hooks[i])
|
||||||
if (handler)
|
|
||||||
{
|
{
|
||||||
vstr_fmt_add_handler(conf, handler);
|
vstr_fmt_add_handler(conf, printf_hooks[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return conf;
|
return conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get vstr config of current thread
|
||||||
|
*/
|
||||||
static inline Vstr_conf *get_vstr_conf()
|
static inline Vstr_conf *get_vstr_conf()
|
||||||
{
|
{
|
||||||
Vstr_conf *conf = NULL;
|
Vstr_conf *conf = NULL;
|
||||||
|
|
||||||
if (vstr_conf)
|
if (vstr_conf)
|
||||||
{
|
{
|
||||||
conf = (Vstr_conf*)vstr_conf->get(vstr_conf);
|
conf = (Vstr_conf*)vstr_conf->get(vstr_conf);
|
||||||
@@ -238,21 +224,6 @@ static inline Vstr_conf *get_vstr_conf()
|
|||||||
return 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
|
* Wrapper functions for printf and alike
|
||||||
*/
|
*/
|
||||||
@@ -265,6 +236,7 @@ int vstr_wrapper_printf(const char *format, ...)
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vstr_wrapper_fprintf(FILE *stream, const char *format, ...)
|
int vstr_wrapper_fprintf(FILE *stream, const char *format, ...)
|
||||||
{
|
{
|
||||||
int written;
|
int written;
|
||||||
@@ -274,6 +246,7 @@ int vstr_wrapper_fprintf(FILE *stream, const char *format, ...)
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vstr_wrapper_sprintf(char *str, const char *format, ...)
|
int vstr_wrapper_sprintf(char *str, const char *format, ...)
|
||||||
{
|
{
|
||||||
int written;
|
int written;
|
||||||
@@ -283,6 +256,7 @@ int vstr_wrapper_sprintf(char *str, const char *format, ...)
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vstr_wrapper_snprintf(char *str, size_t size, const char *format, ...)
|
int vstr_wrapper_snprintf(char *str, size_t size, const char *format, ...)
|
||||||
{
|
{
|
||||||
int written;
|
int written;
|
||||||
@@ -292,6 +266,7 @@ int vstr_wrapper_snprintf(char *str, size_t size, const char *format, ...)
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vstr_wrapper_asprintf(char **str, const char *format, ...)
|
int vstr_wrapper_asprintf(char **str, const char *format, ...)
|
||||||
{
|
{
|
||||||
int written;
|
int written;
|
||||||
@@ -301,13 +276,16 @@ int vstr_wrapper_asprintf(char **str, const char *format, ...)
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int vstr_wrapper_vprintf_internal(Vstr_conf *conf, FILE *stream,
|
static inline int vstr_wrapper_vprintf_internal(Vstr_conf *conf, FILE *stream,
|
||||||
const char *format,
|
const char *format,
|
||||||
va_list args)
|
va_list args)
|
||||||
{
|
{
|
||||||
struct iovec *iov;
|
struct iovec *iov;
|
||||||
int iovcnt, written = 0;
|
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);
|
vstr_add_vfmt(s, 0, format, args);
|
||||||
if (vstr_export_iovec_ptr_all(s, &iov, &iovcnt))
|
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);
|
vstr_free_base(s);
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vstr_wrapper_vprintf(const char *format, va_list args)
|
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)
|
if (conf)
|
||||||
{
|
{
|
||||||
return vstr_wrapper_vprintf_internal(conf, stdout, format, args);
|
return vstr_wrapper_vprintf_internal(conf, stdout, format, args);
|
||||||
}
|
}
|
||||||
return vprintf(format, args);
|
return vprintf(format, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
int vstr_wrapper_vfprintf(FILE *stream, const char *format, va_list 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)
|
if (conf)
|
||||||
{
|
{
|
||||||
return vstr_wrapper_vprintf_internal(conf, stream, format, args);
|
return vstr_wrapper_vprintf_internal(conf, stream, format, args);
|
||||||
}
|
}
|
||||||
return vfprintf(stream, format, args);
|
return vfprintf(stream, format, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int vstr_wrapper_vsnprintf_internal(char *str, size_t size,
|
static inline int vstr_wrapper_vsnprintf_internal(char *str, size_t size,
|
||||||
const char *format,
|
const char *format,
|
||||||
va_list args)
|
va_list args)
|
||||||
{
|
{
|
||||||
Vstr_conf *conf = get_vstr_conf();
|
Vstr_conf *conf;
|
||||||
|
Vstr_base *s;
|
||||||
|
int written;
|
||||||
|
|
||||||
|
conf = get_vstr_conf();
|
||||||
if (conf)
|
if (conf)
|
||||||
{
|
{
|
||||||
int written;
|
s = vstr_make_base(conf);
|
||||||
Vstr_base *s = vstr_make_base(conf);
|
|
||||||
vstr_add_vfmt(s, 0, format, args);
|
vstr_add_vfmt(s, 0, format, args);
|
||||||
written = s->len;
|
written = s->len;
|
||||||
vstr_export_cstr_buf(s, 1, s->len, str, (size > 0) ? size : s->len + 1);
|
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);
|
return vsnprintf(str, size, format, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
int vstr_wrapper_vsprintf(char *str, const char *format, va_list args)
|
int vstr_wrapper_vsprintf(char *str, const char *format, va_list args)
|
||||||
{
|
{
|
||||||
return vstr_wrapper_vsnprintf_internal(str, 0, format, args);
|
return vstr_wrapper_vsnprintf_internal(str, 0, format, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
int vstr_wrapper_vsnprintf(char *str, size_t size, const char *format,
|
int vstr_wrapper_vsnprintf(char *str, size_t size, const char *format,
|
||||||
va_list args)
|
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)
|
int vstr_wrapper_vasprintf(char **str, const char *format, va_list args)
|
||||||
{
|
{
|
||||||
size_t len = 100;
|
size_t len = 100;
|
||||||
int written;
|
int written;
|
||||||
|
|
||||||
*str = malloc(len);
|
*str = malloc(len);
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
@@ -387,60 +383,68 @@ int vstr_wrapper_vasprintf(char **str, const char *format, va_list args)
|
|||||||
}
|
}
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
METHOD(printf_hook_t, add_handler, void,
|
METHOD(printf_hook_t, add_handler, void,
|
||||||
private_printf_hook_t *this, char spec,
|
private_printf_hook_t *this, char spec, printf_hook_function_t hook, ...)
|
||||||
printf_hook_function_t hook, ...)
|
|
||||||
{
|
{
|
||||||
int i = -1;
|
int i = -1;
|
||||||
|
bool failed = FALSE;
|
||||||
printf_hook_handler_t *handler;
|
printf_hook_handler_t *handler;
|
||||||
printf_hook_argtype_t argtype;
|
printf_hook_argtype_t argtype;
|
||||||
va_list args;
|
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, "
|
DBG1(DBG_LIB, "'%c' is not a valid printf hook specifier, "
|
||||||
"not registered!", spec);
|
"not registered!", spec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
handler = malloc_thing(printf_hook_handler_t);
|
INIT(handler,
|
||||||
handler->hook = hook;
|
.hook = hook,
|
||||||
|
);
|
||||||
|
|
||||||
va_start(args, 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)
|
if (++i >= ARGS_MAX)
|
||||||
{
|
{
|
||||||
DBG1(DBG_LIB, "Too many arguments for printf hook with "
|
DBG1(DBG_LIB, "Too many arguments for printf hook with "
|
||||||
"specifier '%c', not registered!", spec);
|
"specifier '%c', not registered!", spec);
|
||||||
va_end(args);
|
failed = TRUE;
|
||||||
free(handler);
|
break;
|
||||||
return;
|
}
|
||||||
|
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);
|
va_end(args);
|
||||||
|
|
||||||
handler->numargs = i + 1;
|
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();
|
Vstr_conf *conf = get_vstr_conf();
|
||||||
handler->name = malloc(2);
|
handler->name = malloc(2);
|
||||||
handler->name[0] = spec;
|
handler->name[0] = spec;
|
||||||
handler->name[1] = '\0';
|
handler->name[1] = '\0';
|
||||||
vstr_fmt_add_handler(conf, handler);
|
vstr_fmt_add_handler(conf, handler);
|
||||||
#endif
|
|
||||||
printf_hooks[SPEC_TO_INDEX(spec)] = handler;
|
printf_hooks[SPEC_TO_INDEX(spec)] = handler;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -453,29 +457,25 @@ METHOD(printf_hook_t, destroy, void,
|
|||||||
private_printf_hook_t *this)
|
private_printf_hook_t *this)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
#ifdef USE_VSTR
|
Vstr_conf *conf;
|
||||||
Vstr_conf *conf = get_vstr_conf();
|
printf_hook_handler_t *handler;
|
||||||
#endif
|
|
||||||
|
|
||||||
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)
|
if (handler)
|
||||||
{
|
{
|
||||||
#ifdef USE_VSTR
|
|
||||||
vstr_fmt_del(conf, handler->name);
|
vstr_fmt_del(conf, handler->name);
|
||||||
free(handler->name);
|
free(handler->name);
|
||||||
#endif
|
|
||||||
free(handler);
|
free(handler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_VSTR
|
|
||||||
/* freeing the Vstr_conf of the main thread */
|
/* freeing the Vstr_conf of the main thread */
|
||||||
vstr_conf->destroy(vstr_conf);
|
vstr_conf->destroy(vstr_conf);
|
||||||
vstr_conf = NULL;
|
vstr_conf = NULL;
|
||||||
vstr_exit();
|
vstr_exit();
|
||||||
#endif
|
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,7 +495,6 @@ printf_hook_t *printf_hook_create()
|
|||||||
|
|
||||||
memset(printf_hooks, 0, sizeof(printf_hooks));
|
memset(printf_hooks, 0, sizeof(printf_hooks));
|
||||||
|
|
||||||
#ifdef USE_VSTR
|
|
||||||
if (!vstr_init())
|
if (!vstr_init())
|
||||||
{
|
{
|
||||||
DBG1(DBG_LIB, "failed to initialize Vstr library!");
|
DBG1(DBG_LIB, "failed to initialize Vstr library!");
|
||||||
@@ -503,8 +502,6 @@ printf_hook_t *printf_hook_create()
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
vstr_conf = thread_value_create((thread_cleanup_t)vstr_free_conf);
|
vstr_conf = thread_value_create((thread_cleanup_t)vstr_free_conf);
|
||||||
#endif
|
|
||||||
|
|
||||||
return &this->public;
|
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