Moved printf hooks to utils folder
authorTobias Brunner <tobias@strongswan.org>
Tue, 16 Oct 2012 13:44:58 +0000 (15:44 +0200)
committerTobias Brunner <tobias@strongswan.org>
Wed, 24 Oct 2012 14:00:50 +0000 (16:00 +0200)
src/libstrongswan/Android.mk
src/libstrongswan/Makefile.am
src/libstrongswan/enum.h
src/libstrongswan/library.h
src/libstrongswan/printf_hook.c [deleted file]
src/libstrongswan/printf_hook.h [deleted file]
src/libstrongswan/utils/printf_hook.c [new file with mode: 0644]
src/libstrongswan/utils/printf_hook.h [new file with mode: 0644]

index 094e1bc..ef9f378 100644 (file)
@@ -3,7 +3,7 @@ include $(CLEAR_VARS)
 
 # copy-n-paste from Makefile.am
 LOCAL_SRC_FILES := \
-library.c chunk.c debug.c enum.c settings.c printf_hook.c \
+library.c chunk.c debug.c enum.c settings.c \
 asn1/asn1.c asn1/asn1_parser.c asn1/oid.c bio/bio_reader.c bio/bio_writer.c \
 collections/blocking_queue.c collections/enumerator.c collections/hashtable.c \
 collections/linked_list.c \
@@ -31,7 +31,7 @@ processing/jobs/callback_job.c processing/processor.c processing/scheduler.c \
 selectors/traffic_selector.c threading/thread.c threading/thread_value.c \
 threading/mutex.c threading/semaphore.c threading/rwlock.c threading/spinlock.c \
 utils.c utils/identification.c utils/lexparser.c \
-utils/optionsfrom.c utils/capabilities.c utils/backtrace.c
+utils/optionsfrom.c utils/capabilities.c utils/backtrace.c utils/printf_hook.c
 
 # adding the plugin source files
 
index 3e549af..77120c6 100644 (file)
@@ -1,7 +1,7 @@
 ipseclib_LTLIBRARIES = libstrongswan.la
 
 libstrongswan_la_SOURCES = \
-library.c chunk.c debug.c enum.c settings.c printf_hook.c \
+library.c chunk.c debug.c enum.c settings.c \
 asn1/asn1.c asn1/asn1_parser.c asn1/oid.c bio/bio_reader.c bio/bio_writer.c \
 collections/blocking_queue.c collections/enumerator.c collections/hashtable.c \
 collections/linked_list.c \
@@ -29,12 +29,12 @@ processing/jobs/callback_job.c processing/processor.c processing/scheduler.c \
 selectors/traffic_selector.c threading/thread.c threading/thread_value.c \
 threading/mutex.c threading/semaphore.c threading/rwlock.c threading/spinlock.c \
 utils.c utils/identification.c utils/lexparser.c \
-utils/optionsfrom.c utils/capabilities.c utils/backtrace.c
+utils/optionsfrom.c utils/capabilities.c utils/backtrace.c utils/printf_hook.c
 
 if USE_DEV_HEADERS
 strongswan_includedir = ${dev_headers}
 nobase_strongswan_include_HEADERS = \
-library.h chunk.h debug.h enum.h settings.h printf_hook.h \
+library.h chunk.h debug.h enum.h settings.h \
 asn1/asn1.h asn1/asn1_parser.h asn1/oid.h bio/bio_reader.h bio/bio_writer.h \
 collections/blocking_queue.h collections/enumerator.h collections/hashtable.h \
 collections/linked_list.h \
@@ -70,7 +70,7 @@ threading/mutex.h threading/condvar.h threading/spinlock.h threading/semaphore.h
 threading/rwlock.h threading/rwlock_condvar.h threading/lock_profiler.h \
 utils.h utils/identification.h utils/lexparser.h \
 utils/optionsfrom.h utils/capabilities.h utils/backtrace.h \
-utils/leak_detective.h utils/integrity_checker.h
+utils/leak_detective.h utils/printf_hook.h utils/integrity_checker.h
 endif
 
 library.lo :   $(top_builddir)/config.status
index 8403712..0ed6068 100644 (file)
@@ -22,7 +22,7 @@
 #ifndef ENUM_H_
 #define ENUM_H_
 
-#include "printf_hook.h"
+#include "utils/printf_hook.h"
 
 typedef struct enum_name_t enum_name_t;
 
index ad31c1b..c8e8827 100644 (file)
@@ -80,7 +80,8 @@
 # error config.h not included, pass "-include [...]/config.h" to gcc
 #endif
 
-#include "printf_hook.h"
+/* make sure we include printf_hook.h first */
+#include "utils/printf_hook.h"
 #include "utils.h"
 #include "chunk.h"
 #include "settings.h"
diff --git a/src/libstrongswan/printf_hook.c b/src/libstrongswan/printf_hook.c
deleted file mode 100644 (file)
index 6e51aa4..0000000
+++ /dev/null
@@ -1,511 +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.
- */
-
-#include "printf_hook.h"
-
-#include "utils.h"
-#include "debug.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;
-
-#define PRINTF_BUF_LEN 8192
-#define ARGS_MAX 3
-
-/**
- * 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
-        */
-       int argtypes[ARGS_MAX];
-
-#ifdef USE_VSTR
-       /**
-        * name required for Vstr
-        */
-       char *name;
-#endif
-};
-
-/* A-Z | 6 other chars | a-z */
-#define NUM_HANDLERS 58
-static printf_hook_handler_t *printf_hooks[NUM_HANDLERS];
-
-#define SPEC_TO_INDEX(spec) ((int)(spec) - (int)'A')
-#define IS_VALID_SPEC(spec) (SPEC_TO_INDEX(spec) > -1 && SPEC_TO_INDEX(spec) < NUM_HANDLERS)
-
-#if !defined(USE_VSTR) && \
-       (defined(HAVE_PRINTF_FUNCTION) || defined(HAVE_PRINTF_SPECIFIER))
-
-/**
- * Printf hook print function. This is actually of type "printf_function",
- * however glibc does it typedef to function, but uclibc to a pointer.
- * So we redefine it here.
- */
-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
- * initialization or after destruction.
- */
-#undef vprintf
-#undef vfprintf
-#undef vsnprintf
-
-/**
- * Vstr custom format specifier callback function.
- */
-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_data_t data = {
-               .base = base,
-               .pos = pos,
-       };
-
-       for (i = 0; i < handler->numargs; i++)
-       {
-               switch(handler->argtypes[i])
-               {
-                       case PRINTF_HOOK_ARGTYPE_INT:
-                               args[i] = VSTR_FMT_CB_ARG_PTR(fmt_spec, i);
-                               break;
-                       case PRINTF_HOOK_ARGTYPE_POINTER:
-                               args[i] = &VSTR_FMT_CB_ARG_PTR(fmt_spec, i);
-                               break;
-               }
-       }
-
-       spec.hash = fmt_spec->fmt_hash;
-       spec.plus = fmt_spec->fmt_plus;
-       spec.minus = fmt_spec->fmt_minus;
-       spec.width = fmt_spec->fmt_field_width;
-
-       handler->hook(&data, &spec, args);
-       return 1;
-}
-
-/**
- * Add a custom format handler to the given Vstr_conf object
- */
-static void vstr_fmt_add_handler(Vstr_conf *conf, printf_hook_handler_t *handler)
-{
-       int *at = handler->argtypes;
-       switch(handler->numargs)
-       {
-               case 1:
-                       vstr_fmt_add(conf, handler->name, custom_fmt_cb, at[0],
-                                                VSTR_TYPE_FMT_END);
-                       break;
-               case 2:
-                       vstr_fmt_add(conf, handler->name, custom_fmt_cb, at[0],
-                                                at[1], VSTR_TYPE_FMT_END);
-                       break;
-               case 3:
-                       vstr_fmt_add(conf, handler->name, custom_fmt_cb, at[0],
-                                                at[1], at[2], VSTR_TYPE_FMT_END);
-                       break;
-       }
-}
-
-/**
- * Management of thread-specific Vstr_conf objects
- */
-#include <threading/thread_value.h>
-
-static thread_value_t *vstr_conf = NULL;
-
-static Vstr_conf *create_vstr_conf()
-{
-       int i;
-       Vstr_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)
-       {
-               printf_hook_handler_t *handler = printf_hooks[i];
-               if (handler)
-               {
-                       vstr_fmt_add_handler(conf, handler);
-               }
-       }
-       return conf;
-}
-
-static inline Vstr_conf *get_vstr_conf()
-{
-       Vstr_conf *conf = NULL;
-       if (vstr_conf)
-       {
-               conf = (Vstr_conf*)vstr_conf->get(vstr_conf);
-               if (!conf)
-               {
-                       conf = create_vstr_conf();
-                       vstr_conf->set(vstr_conf, 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
- */
-int vstr_wrapper_printf(const char *format, ...)
-{
-       int written;
-       va_list args;
-       va_start(args, format);
-       written = vstr_wrapper_vprintf(format, args);
-       va_end(args);
-       return written;
-}
-int vstr_wrapper_fprintf(FILE *stream, const char *format, ...)
-{
-       int written;
-       va_list args;
-       va_start(args, format);
-       written = vstr_wrapper_vfprintf(stream, format, args);
-       va_end(args);
-       return written;
-}
-int vstr_wrapper_sprintf(char *str, const char *format, ...)
-{
-       int written;
-       va_list args;
-       va_start(args, format);
-       written = vstr_wrapper_vsprintf(str, format, args);
-       va_end(args);
-       return written;
-}
-int vstr_wrapper_snprintf(char *str, size_t size, const char *format, ...)
-{
-       int written;
-       va_list args;
-       va_start(args, format);
-       written = vstr_wrapper_vsnprintf(str, size, format, args);
-       va_end(args);
-       return written;
-}
-int vstr_wrapper_asprintf(char **str, const char *format, ...)
-{
-       int written;
-       va_list args;
-       va_start(args, format);
-       written = vstr_wrapper_vasprintf(str, format, args);
-       va_end(args);
-       return written;
-}
-static inline int vstr_wrapper_vprintf_internal(Vstr_conf *conf, int fd,
-                                                                                               const char *format,
-                                                                                               va_list args)
-{
-       int written;
-       Vstr_base *s = vstr_make_base(conf);
-       vstr_add_vfmt(s, 0, format, args);
-       written = s->len;
-       while (s->len)
-       {
-               if (!vstr_sc_write_fd(s, 1, s->len, fd, NULL))
-               {
-                       if (errno != EAGAIN && errno != EINTR)
-                       {
-                               written -= s->len;
-                               break;
-                       }
-               }
-       }
-       vstr_free_base(s);
-       return written;
-}
-int vstr_wrapper_vprintf(const char *format, va_list args)
-{
-       Vstr_conf *conf = get_vstr_conf();
-       if (conf)
-       {
-               return vstr_wrapper_vprintf_internal(conf, STDOUT_FILENO, format, args);
-       }
-       return vprintf(format, args);
-}
-int vstr_wrapper_vfprintf(FILE *stream, const char *format, va_list args)
-{
-       Vstr_conf *conf = get_vstr_conf();
-       if (conf)
-       {
-               return vstr_wrapper_vprintf_internal(conf, fileno(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();
-       if (conf)
-       {
-               int written;
-               Vstr_base *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);
-               vstr_free_base(s);
-               return written;
-       }
-       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;
-}
-int vstr_wrapper_vasprintf(char **str, const char *format, va_list args)
-{
-       size_t len = 100;
-       int written;
-       *str = malloc(len);
-       while (TRUE)
-       {
-               va_list ac;
-               va_copy(ac, args);
-               written = vstr_wrapper_vsnprintf_internal(*str, len, format, ac);
-               va_end(ac);
-               if (written < len)
-               {
-                       break;
-               }
-               len = written + 1;
-               *str = realloc(*str, len);
-       }
-       return written;
-}
-#endif
-
-METHOD(printf_hook_t, add_handler, void,
-       private_printf_hook_t *this, char spec,
-                                               printf_hook_function_t hook, ...)
-{
-       int i = -1;
-       printf_hook_handler_t *handler;
-       printf_hook_argtype_t argtype;
-       va_list args;
-
-       if (!IS_VALID_SPEC(spec))
-       {
-               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;
-
-       va_start(args, hook);
-       while ((argtype = va_arg(args, printf_hook_argtype_t)) != PRINTF_HOOK_ARGTYPE_END)
-       {
-               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;
-               }
-               handler->argtypes[i] = argtype;
-       }
-       va_end(args);
-
-       handler->numargs = i + 1;
-
-       if (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
-       {
-               free(handler);
-       }
-}
-
-METHOD(printf_hook_t, destroy, void,
-       private_printf_hook_t *this)
-{
-       int i;
-#ifdef USE_VSTR
-       Vstr_conf *conf = get_vstr_conf();
-#endif
-
-       for (i = 0; i < NUM_HANDLERS; ++i)
-       {
-               printf_hook_handler_t *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_free_conf(conf);
-       vstr_exit();
-#endif
-       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));
-
-#ifdef USE_VSTR
-       if (!vstr_init())
-       {
-               DBG1(DBG_LIB, "failed to initialize Vstr library!");
-               free(this);
-               return NULL;
-       }
-       vstr_conf = thread_value_create((thread_cleanup_t)vstr_free_conf);
-#endif
-
-       return &this->public;
-}
-
diff --git a/src/libstrongswan/printf_hook.h b/src/libstrongswan/printf_hook.h
deleted file mode 100644 (file)
index 7d3f23b..0000000
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (C) 2009 Tobias Brunner
- * Copyright (C) 2006-2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup printf_hook printf_hook
- * @{ @ingroup libstrongswan
- */
-
-#ifndef PRINTF_HOOK_H_
-#define PRINTF_HOOK_H_
-
-typedef struct printf_hook_t printf_hook_t;
-typedef struct printf_hook_spec_t printf_hook_spec_t;
-typedef struct printf_hook_data_t printf_hook_data_t;
-typedef enum printf_hook_argtype_t printf_hook_argtype_t;
-
-#if !defined(USE_VSTR) && \
-       !defined(HAVE_PRINTF_FUNCTION) && \
-       !defined(HAVE_PRINTF_SPECIFIER)
-/* assume newer glibc register_printf_specifier if none given */
-#define HAVE_PRINTF_SPECIFIER
-#endif
-
-#if !defined(USE_VSTR) && \
-       (defined(HAVE_PRINTF_FUNCTION) || defined(HAVE_PRINTF_SPECIFIER))
-
-#include <stdio.h>
-#include <printf.h>
-
-enum printf_hook_argtype_t {
-       PRINTF_HOOK_ARGTYPE_END = -1,
-       PRINTF_HOOK_ARGTYPE_INT = PA_INT,
-       PRINTF_HOOK_ARGTYPE_POINTER = PA_POINTER,
-};
-
-/**
- * Data to pass to a printf hook.
- */
-struct printf_hook_data_t {
-
-       /**
-        * Output FILE stream
-        */
-       FILE *stream;;
-};
-
-/**
- * Helper macro to be used in printf hook callbacks.
- */
-#define print_in_hook(data, fmt, ...) ({\
-       ssize_t _written = fprintf(data->stream, fmt, ##__VA_ARGS__);\
-       if (_written < 0)\
-       {\
-               _written = 0;\
-       }\
-       _written;\
-})
-
-#else
-
-#include <vstr.h>
-
-enum printf_hook_argtype_t {
-       PRINTF_HOOK_ARGTYPE_END = VSTR_TYPE_FMT_END,
-       PRINTF_HOOK_ARGTYPE_INT = VSTR_TYPE_FMT_INT,
-       PRINTF_HOOK_ARGTYPE_POINTER = VSTR_TYPE_FMT_PTR_VOID,
-};
-
-/**
- * Redefining printf and alike
- */
-#include <stdio.h>
-#include <stdarg.h>
-
-int vstr_wrapper_printf(const char *format, ...);
-int vstr_wrapper_fprintf(FILE *stream, const char *format, ...);
-int vstr_wrapper_sprintf(char *str, const char *format, ...);
-int vstr_wrapper_snprintf(char *str, size_t size, const char *format, ...);
-int vstr_wrapper_asprintf(char **str, const char *format, ...);
-
-int vstr_wrapper_vprintf(const char *format, va_list ap);
-int vstr_wrapper_vfprintf(FILE *stream, const char *format, va_list ap);
-int vstr_wrapper_vsprintf(char *str, const char *format, va_list ap);
-int vstr_wrapper_vsnprintf(char *str, size_t size, const char *format, va_list ap);
-int vstr_wrapper_vasprintf(char **str, const char *format, va_list ap);
-
-#ifdef printf
-#undef printf
-#endif
-#ifdef fprintf
-#undef fprintf
-#endif
-#ifdef sprintf
-#undef sprintf
-#endif
-#ifdef snprintf
-#undef snprintf
-#endif
-#ifdef asprintf
-#undef asprintf
-#endif
-#ifdef vprintf
-#undef vprintf
-#endif
-#ifdef vfprintf
-#undef vfprintf
-#endif
-#ifdef vsprintf
-#undef vsprintf
-#endif
-#ifdef vsnprintf
-#undef vsnprintf
-#endif
-#ifdef vasprintf
-#undef vasprintf
-#endif
-
-#define printf vstr_wrapper_printf
-#define fprintf vstr_wrapper_fprintf
-#define sprintf vstr_wrapper_sprintf
-#define snprintf vstr_wrapper_snprintf
-#define asprintf vstr_wrapper_asprintf
-
-#define vprintf vstr_wrapper_vprintf
-#define vfprintf vstr_wrapper_vfprintf
-#define vsprintf vstr_wrapper_vsprintf
-#define vsnprintf vstr_wrapper_vsnprintf
-#define vasprintf vstr_wrapper_vasprintf
-
-/**
- * Data to pass to a printf hook.
- */
-struct printf_hook_data_t {
-
-       /**
-        * Base to append printf to
-        */
-       Vstr_base *base;
-
-       /**
-        * Position in base to write to
-        */
-       size_t pos;
-};
-
-/**
- * Wrapper around vstr_add_vfmt(), avoids having to link all users of
- * print_in_hook() against libvstr.
- *
- * @param base         Vstr_string to add string to
- * @param pos          position to write to
- * @param fmt          format string
- * @param ...          arguments
- * @return                     number of characters written
- */
-size_t vstr_print_in_hook(struct Vstr_base *base, size_t pos, const char *fmt,
-                                                 ...);
-
-/**
- * Helper macro to be used in printf hook callbacks.
- */
-#define print_in_hook(data, fmt, ...) ({\
-       size_t _written; \
-       _written = vstr_print_in_hook(data->base, data->pos, fmt, ##__VA_ARGS__);\
-       data->pos += _written;\
-       _written;\
-})
-
-#endif
-
-/**
- * Callback function type for printf hooks.
- *
- * @param data         hook data, to pass to print_in_hook()
- * @param spec         format specifier
- * @param args         arguments array
- * @return                     number of characters written
- */
-typedef int (*printf_hook_function_t)(printf_hook_data_t *data,
-                                                                         printf_hook_spec_t *spec,
-                                                                         const void *const *args);
-
-/**
- * Properties of the format specifier
- */
-struct printf_hook_spec_t {
-       /**
-        * TRUE if a '#' was used in the format specifier
-        */
-       int hash;
-
-       /**
-        * TRUE if a '-' was used in the format specifier
-        */
-       int minus;
-
-       /**
-        * TRUE if a '+' was used in the format specifier
-        */
-       int plus;
-
-       /**
-        * The width as given in the format specifier.
-        */
-       int width;
-};
-
-/**
- * Printf handler management.
- */
-struct printf_hook_t {
-
-       /**
-        * Register a printf handler.
-        *
-        * @param spec          printf hook format character
-        * @param hook          hook function
-        * @param ...           list of PRINTF_HOOK_ARGTYPE_*, MUST end with PRINTF_HOOK_ARGTYPE_END
-        */
-       void (*add_handler)(printf_hook_t *this, char spec,
-                                               printf_hook_function_t hook, ...);
-
-       /**
-        * Destroy a printf_hook instance.
-        */
-       void (*destroy)(printf_hook_t *this);
-};
-
-/**
- * Create a printf_hook instance.
- */
-printf_hook_t *printf_hook_create();
-
-#endif /** PRINTF_HOOK_H_ @}*/
diff --git a/src/libstrongswan/utils/printf_hook.c b/src/libstrongswan/utils/printf_hook.c
new file mode 100644 (file)
index 0000000..6e51aa4
--- /dev/null
@@ -0,0 +1,511 @@
+/*
+ * 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.
+ */
+
+#include "printf_hook.h"
+
+#include "utils.h"
+#include "debug.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;
+
+#define PRINTF_BUF_LEN 8192
+#define ARGS_MAX 3
+
+/**
+ * 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
+        */
+       int argtypes[ARGS_MAX];
+
+#ifdef USE_VSTR
+       /**
+        * name required for Vstr
+        */
+       char *name;
+#endif
+};
+
+/* A-Z | 6 other chars | a-z */
+#define NUM_HANDLERS 58
+static printf_hook_handler_t *printf_hooks[NUM_HANDLERS];
+
+#define SPEC_TO_INDEX(spec) ((int)(spec) - (int)'A')
+#define IS_VALID_SPEC(spec) (SPEC_TO_INDEX(spec) > -1 && SPEC_TO_INDEX(spec) < NUM_HANDLERS)
+
+#if !defined(USE_VSTR) && \
+       (defined(HAVE_PRINTF_FUNCTION) || defined(HAVE_PRINTF_SPECIFIER))
+
+/**
+ * Printf hook print function. This is actually of type "printf_function",
+ * however glibc does it typedef to function, but uclibc to a pointer.
+ * So we redefine it here.
+ */
+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
+ * initialization or after destruction.
+ */
+#undef vprintf
+#undef vfprintf
+#undef vsnprintf
+
+/**
+ * Vstr custom format specifier callback function.
+ */
+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_data_t data = {
+               .base = base,
+               .pos = pos,
+       };
+
+       for (i = 0; i < handler->numargs; i++)
+       {
+               switch(handler->argtypes[i])
+               {
+                       case PRINTF_HOOK_ARGTYPE_INT:
+                               args[i] = VSTR_FMT_CB_ARG_PTR(fmt_spec, i);
+                               break;
+                       case PRINTF_HOOK_ARGTYPE_POINTER:
+                               args[i] = &VSTR_FMT_CB_ARG_PTR(fmt_spec, i);
+                               break;
+               }
+       }
+
+       spec.hash = fmt_spec->fmt_hash;
+       spec.plus = fmt_spec->fmt_plus;
+       spec.minus = fmt_spec->fmt_minus;
+       spec.width = fmt_spec->fmt_field_width;
+
+       handler->hook(&data, &spec, args);
+       return 1;
+}
+
+/**
+ * Add a custom format handler to the given Vstr_conf object
+ */
+static void vstr_fmt_add_handler(Vstr_conf *conf, printf_hook_handler_t *handler)
+{
+       int *at = handler->argtypes;
+       switch(handler->numargs)
+       {
+               case 1:
+                       vstr_fmt_add(conf, handler->name, custom_fmt_cb, at[0],
+                                                VSTR_TYPE_FMT_END);
+                       break;
+               case 2:
+                       vstr_fmt_add(conf, handler->name, custom_fmt_cb, at[0],
+                                                at[1], VSTR_TYPE_FMT_END);
+                       break;
+               case 3:
+                       vstr_fmt_add(conf, handler->name, custom_fmt_cb, at[0],
+                                                at[1], at[2], VSTR_TYPE_FMT_END);
+                       break;
+       }
+}
+
+/**
+ * Management of thread-specific Vstr_conf objects
+ */
+#include <threading/thread_value.h>
+
+static thread_value_t *vstr_conf = NULL;
+
+static Vstr_conf *create_vstr_conf()
+{
+       int i;
+       Vstr_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)
+       {
+               printf_hook_handler_t *handler = printf_hooks[i];
+               if (handler)
+               {
+                       vstr_fmt_add_handler(conf, handler);
+               }
+       }
+       return conf;
+}
+
+static inline Vstr_conf *get_vstr_conf()
+{
+       Vstr_conf *conf = NULL;
+       if (vstr_conf)
+       {
+               conf = (Vstr_conf*)vstr_conf->get(vstr_conf);
+               if (!conf)
+               {
+                       conf = create_vstr_conf();
+                       vstr_conf->set(vstr_conf, 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
+ */
+int vstr_wrapper_printf(const char *format, ...)
+{
+       int written;
+       va_list args;
+       va_start(args, format);
+       written = vstr_wrapper_vprintf(format, args);
+       va_end(args);
+       return written;
+}
+int vstr_wrapper_fprintf(FILE *stream, const char *format, ...)
+{
+       int written;
+       va_list args;
+       va_start(args, format);
+       written = vstr_wrapper_vfprintf(stream, format, args);
+       va_end(args);
+       return written;
+}
+int vstr_wrapper_sprintf(char *str, const char *format, ...)
+{
+       int written;
+       va_list args;
+       va_start(args, format);
+       written = vstr_wrapper_vsprintf(str, format, args);
+       va_end(args);
+       return written;
+}
+int vstr_wrapper_snprintf(char *str, size_t size, const char *format, ...)
+{
+       int written;
+       va_list args;
+       va_start(args, format);
+       written = vstr_wrapper_vsnprintf(str, size, format, args);
+       va_end(args);
+       return written;
+}
+int vstr_wrapper_asprintf(char **str, const char *format, ...)
+{
+       int written;
+       va_list args;
+       va_start(args, format);
+       written = vstr_wrapper_vasprintf(str, format, args);
+       va_end(args);
+       return written;
+}
+static inline int vstr_wrapper_vprintf_internal(Vstr_conf *conf, int fd,
+                                                                                               const char *format,
+                                                                                               va_list args)
+{
+       int written;
+       Vstr_base *s = vstr_make_base(conf);
+       vstr_add_vfmt(s, 0, format, args);
+       written = s->len;
+       while (s->len)
+       {
+               if (!vstr_sc_write_fd(s, 1, s->len, fd, NULL))
+               {
+                       if (errno != EAGAIN && errno != EINTR)
+                       {
+                               written -= s->len;
+                               break;
+                       }
+               }
+       }
+       vstr_free_base(s);
+       return written;
+}
+int vstr_wrapper_vprintf(const char *format, va_list args)
+{
+       Vstr_conf *conf = get_vstr_conf();
+       if (conf)
+       {
+               return vstr_wrapper_vprintf_internal(conf, STDOUT_FILENO, format, args);
+       }
+       return vprintf(format, args);
+}
+int vstr_wrapper_vfprintf(FILE *stream, const char *format, va_list args)
+{
+       Vstr_conf *conf = get_vstr_conf();
+       if (conf)
+       {
+               return vstr_wrapper_vprintf_internal(conf, fileno(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();
+       if (conf)
+       {
+               int written;
+               Vstr_base *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);
+               vstr_free_base(s);
+               return written;
+       }
+       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;
+}
+int vstr_wrapper_vasprintf(char **str, const char *format, va_list args)
+{
+       size_t len = 100;
+       int written;
+       *str = malloc(len);
+       while (TRUE)
+       {
+               va_list ac;
+               va_copy(ac, args);
+               written = vstr_wrapper_vsnprintf_internal(*str, len, format, ac);
+               va_end(ac);
+               if (written < len)
+               {
+                       break;
+               }
+               len = written + 1;
+               *str = realloc(*str, len);
+       }
+       return written;
+}
+#endif
+
+METHOD(printf_hook_t, add_handler, void,
+       private_printf_hook_t *this, char spec,
+                                               printf_hook_function_t hook, ...)
+{
+       int i = -1;
+       printf_hook_handler_t *handler;
+       printf_hook_argtype_t argtype;
+       va_list args;
+
+       if (!IS_VALID_SPEC(spec))
+       {
+               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;
+
+       va_start(args, hook);
+       while ((argtype = va_arg(args, printf_hook_argtype_t)) != PRINTF_HOOK_ARGTYPE_END)
+       {
+               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;
+               }
+               handler->argtypes[i] = argtype;
+       }
+       va_end(args);
+
+       handler->numargs = i + 1;
+
+       if (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
+       {
+               free(handler);
+       }
+}
+
+METHOD(printf_hook_t, destroy, void,
+       private_printf_hook_t *this)
+{
+       int i;
+#ifdef USE_VSTR
+       Vstr_conf *conf = get_vstr_conf();
+#endif
+
+       for (i = 0; i < NUM_HANDLERS; ++i)
+       {
+               printf_hook_handler_t *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_free_conf(conf);
+       vstr_exit();
+#endif
+       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));
+
+#ifdef USE_VSTR
+       if (!vstr_init())
+       {
+               DBG1(DBG_LIB, "failed to initialize Vstr library!");
+               free(this);
+               return NULL;
+       }
+       vstr_conf = thread_value_create((thread_cleanup_t)vstr_free_conf);
+#endif
+
+       return &this->public;
+}
+
diff --git a/src/libstrongswan/utils/printf_hook.h b/src/libstrongswan/utils/printf_hook.h
new file mode 100644 (file)
index 0000000..1425910
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * 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_ @}*/