summaryrefslogtreecommitdiff
path: root/src/libstrongswan/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/utils')
-rw-r--r--src/libstrongswan/utils/backtrace.c4
-rw-r--r--src/libstrongswan/utils/chunk.c36
-rw-r--r--src/libstrongswan/utils/chunk.h9
-rw-r--r--src/libstrongswan/utils/enum.h2
-rw-r--r--src/libstrongswan/utils/identification.c2
-rw-r--r--src/libstrongswan/utils/leak_detective.c1
-rw-r--r--src/libstrongswan/utils/printf_hook.h247
-rw-r--r--src/libstrongswan/utils/printf_hook/printf_hook.h121
-rw-r--r--src/libstrongswan/utils/printf_hook/printf_hook_builtin.c1168
-rw-r--r--src/libstrongswan/utils/printf_hook/printf_hook_builtin.h82
-rw-r--r--src/libstrongswan/utils/printf_hook/printf_hook_glibc.c244
-rw-r--r--src/libstrongswan/utils/printf_hook/printf_hook_vstr.c (renamed from src/libstrongswan/utils/printf_hook.c)283
-rw-r--r--src/libstrongswan/utils/printf_hook/printf_hook_vstr.h83
-rw-r--r--src/libstrongswan/utils/utils.c46
-rw-r--r--src/libstrongswan/utils/utils.h53
15 files changed, 1973 insertions, 408 deletions
diff --git a/src/libstrongswan/utils/backtrace.c b/src/libstrongswan/utils/backtrace.c
index 93031908a..fb2c4d1e8 100644
--- a/src/libstrongswan/utils/backtrace.c
+++ b/src/libstrongswan/utils/backtrace.c
@@ -536,7 +536,7 @@ METHOD(backtrace_t, create_frame_enumerator, enumerator_t*,
return &enumerator->public;
}
-METHOD(backtrace_t, clone, backtrace_t*,
+METHOD(backtrace_t, clone_, backtrace_t*,
private_backtrace_t *this)
{
private_backtrace_t *clone;
@@ -593,7 +593,7 @@ static backtrace_t get_methods()
.log = _log_,
.contains_function = _contains_function,
.equals = _equals,
- .clone = _clone,
+ .clone = _clone_,
.create_frame_enumerator = _create_frame_enumerator,
.destroy = _destroy,
};
diff --git a/src/libstrongswan/utils/chunk.c b/src/libstrongswan/utils/chunk.c
index 04f3eea7d..644b8060f 100644
--- a/src/libstrongswan/utils/chunk.c
+++ b/src/libstrongswan/utils/chunk.c
@@ -243,6 +243,38 @@ bool chunk_write(chunk_t chunk, char *path, char *label, mode_t mask, bool force
return good;
}
+/**
+ * Described in header.
+ */
+chunk_t chunk_from_fd(int fd)
+{
+ char buf[8096];
+ char *pos = buf;
+ ssize_t len, total = 0;
+
+ while (TRUE)
+ {
+ len = read(fd, pos, buf + sizeof(buf) - pos);
+ if (len < 0)
+ {
+ DBG1(DBG_LIB, "reading from file descriptor failed: %s",
+ strerror(errno));
+ return chunk_empty;
+ }
+ if (len == 0)
+ {
+ break;
+ }
+ total += len;
+ if (total == sizeof(buf))
+ {
+ DBG1(DBG_LIB, "buffer too small to read from file descriptor");
+ return chunk_empty;
+ }
+ }
+ return chunk_clone(chunk_create(buf, total));
+}
+
/** hex conversion digits */
static char hexdig_upper[] = "0123456789ABCDEF";
@@ -797,7 +829,7 @@ int chunk_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
chunk_t copy = *chunk;
int written = 0;
- if (!spec->hash)
+ if (!spec->hash && !spec->plus)
{
u_int chunk_len = chunk->len;
const void *new_args[] = {&chunk->ptr, &chunk_len};
@@ -810,7 +842,7 @@ int chunk_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
{
first = FALSE;
}
- else
+ else if (!spec->plus)
{
written += print_in_hook(data, ":");
}
diff --git a/src/libstrongswan/utils/chunk.h b/src/libstrongswan/utils/chunk.h
index 34ba77357..d3751da70 100644
--- a/src/libstrongswan/utils/chunk.h
+++ b/src/libstrongswan/utils/chunk.h
@@ -100,6 +100,14 @@ void chunk_split(chunk_t chunk, const char *mode, ...);
bool chunk_write(chunk_t chunk, char *path, char *label, mode_t mask, bool force);
/**
+ * Store data read from FD into a chunk
+ *
+ * @param fd file descriptor to read from
+ * @return chunk or chunk_empty on failure
+ */
+chunk_t chunk_from_fd(int fd);
+
+/**
* Convert a chunk of data to hex encoding.
*
* The resulting string is '\\0' terminated, but the chunk does not include
@@ -368,6 +376,7 @@ u_int64_t chunk_mac(chunk_t chunk, u_char *key);
* Arguments are:
* chunk_t *chunk
* Use #-modifier to print a compact version
+ * Use +-modifier to print a compact version without separator
*/
int chunk_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
const void *const *args);
diff --git a/src/libstrongswan/utils/enum.h b/src/libstrongswan/utils/enum.h
index df8dbf8c1..a2f97d05e 100644
--- a/src/libstrongswan/utils/enum.h
+++ b/src/libstrongswan/utils/enum.h
@@ -22,7 +22,7 @@
#ifndef ENUM_H_
#define ENUM_H_
-#include "printf_hook.h"
+#include <utils/printf_hook/printf_hook.h>
typedef struct enum_name_t enum_name_t;
diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c
index 5df3e5fe2..9c43ad570 100644
--- a/src/libstrongswan/utils/identification.c
+++ b/src/libstrongswan/utils/identification.c
@@ -602,7 +602,7 @@ static bool compare_dn(chunk_t t_dn, chunk_t o_dn, int *wc)
}
}
/* try a binary compare */
- if (memeq(t_dn.ptr, o_dn.ptr, t_dn.len))
+ if (chunk_equals(t_dn, o_dn))
{
return TRUE;
}
diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c
index ffbc62085..725e04f7c 100644
--- a/src/libstrongswan/utils/leak_detective.c
+++ b/src/libstrongswan/utils/leak_detective.c
@@ -511,6 +511,7 @@ char *whitelist[] = {
"getspnam_r",
"getpwuid_r",
"initgroups",
+ "tzset",
/* ignore dlopen, as we do not dlclose to get proper leak reports */
"dlopen",
"dlerror",
diff --git a/src/libstrongswan/utils/printf_hook.h b/src/libstrongswan/utils/printf_hook.h
deleted file mode 100644
index 1425910be..000000000
--- a/src/libstrongswan/utils/printf_hook.h
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (C) 2009 Tobias Brunner
- * Copyright (C) 2006-2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup printf_hook printf_hook
- * @{ @ingroup utils
- */
-
-#ifndef PRINTF_HOOK_H_
-#define PRINTF_HOOK_H_
-
-typedef struct printf_hook_t printf_hook_t;
-typedef struct printf_hook_spec_t printf_hook_spec_t;
-typedef struct printf_hook_data_t printf_hook_data_t;
-typedef enum printf_hook_argtype_t printf_hook_argtype_t;
-
-#if !defined(USE_VSTR) && \
- !defined(HAVE_PRINTF_FUNCTION) && \
- !defined(HAVE_PRINTF_SPECIFIER)
-/* assume newer glibc register_printf_specifier if none given */
-#define HAVE_PRINTF_SPECIFIER
-#endif
-
-#if !defined(USE_VSTR) && \
- (defined(HAVE_PRINTF_FUNCTION) || defined(HAVE_PRINTF_SPECIFIER))
-
-#include <stdio.h>
-#include <printf.h>
-
-enum printf_hook_argtype_t {
- PRINTF_HOOK_ARGTYPE_END = -1,
- PRINTF_HOOK_ARGTYPE_INT = PA_INT,
- PRINTF_HOOK_ARGTYPE_POINTER = PA_POINTER,
-};
-
-/**
- * Data to pass to a printf hook.
- */
-struct printf_hook_data_t {
-
- /**
- * Output FILE stream
- */
- FILE *stream;;
-};
-
-/**
- * Helper macro to be used in printf hook callbacks.
- */
-#define print_in_hook(data, fmt, ...) ({\
- ssize_t _written = fprintf(data->stream, fmt, ##__VA_ARGS__);\
- if (_written < 0)\
- {\
- _written = 0;\
- }\
- _written;\
-})
-
-#else
-
-#include <vstr.h>
-
-enum printf_hook_argtype_t {
- PRINTF_HOOK_ARGTYPE_END = VSTR_TYPE_FMT_END,
- PRINTF_HOOK_ARGTYPE_INT = VSTR_TYPE_FMT_INT,
- PRINTF_HOOK_ARGTYPE_POINTER = VSTR_TYPE_FMT_PTR_VOID,
-};
-
-/**
- * Redefining printf and alike
- */
-#include <stdio.h>
-#include <stdarg.h>
-
-int vstr_wrapper_printf(const char *format, ...);
-int vstr_wrapper_fprintf(FILE *stream, const char *format, ...);
-int vstr_wrapper_sprintf(char *str, const char *format, ...);
-int vstr_wrapper_snprintf(char *str, size_t size, const char *format, ...);
-int vstr_wrapper_asprintf(char **str, const char *format, ...);
-
-int vstr_wrapper_vprintf(const char *format, va_list ap);
-int vstr_wrapper_vfprintf(FILE *stream, const char *format, va_list ap);
-int vstr_wrapper_vsprintf(char *str, const char *format, va_list ap);
-int vstr_wrapper_vsnprintf(char *str, size_t size, const char *format, va_list ap);
-int vstr_wrapper_vasprintf(char **str, const char *format, va_list ap);
-
-#ifdef printf
-#undef printf
-#endif
-#ifdef fprintf
-#undef fprintf
-#endif
-#ifdef sprintf
-#undef sprintf
-#endif
-#ifdef snprintf
-#undef snprintf
-#endif
-#ifdef asprintf
-#undef asprintf
-#endif
-#ifdef vprintf
-#undef vprintf
-#endif
-#ifdef vfprintf
-#undef vfprintf
-#endif
-#ifdef vsprintf
-#undef vsprintf
-#endif
-#ifdef vsnprintf
-#undef vsnprintf
-#endif
-#ifdef vasprintf
-#undef vasprintf
-#endif
-
-#define printf vstr_wrapper_printf
-#define fprintf vstr_wrapper_fprintf
-#define sprintf vstr_wrapper_sprintf
-#define snprintf vstr_wrapper_snprintf
-#define asprintf vstr_wrapper_asprintf
-
-#define vprintf vstr_wrapper_vprintf
-#define vfprintf vstr_wrapper_vfprintf
-#define vsprintf vstr_wrapper_vsprintf
-#define vsnprintf vstr_wrapper_vsnprintf
-#define vasprintf vstr_wrapper_vasprintf
-
-/**
- * Data to pass to a printf hook.
- */
-struct printf_hook_data_t {
-
- /**
- * Base to append printf to
- */
- Vstr_base *base;
-
- /**
- * Position in base to write to
- */
- size_t pos;
-};
-
-/**
- * Wrapper around vstr_add_vfmt(), avoids having to link all users of
- * print_in_hook() against libvstr.
- *
- * @param base Vstr_string to add string to
- * @param pos position to write to
- * @param fmt format string
- * @param ... arguments
- * @return number of characters written
- */
-size_t vstr_print_in_hook(struct Vstr_base *base, size_t pos, const char *fmt,
- ...);
-
-/**
- * Helper macro to be used in printf hook callbacks.
- */
-#define print_in_hook(data, fmt, ...) ({\
- size_t _written; \
- _written = vstr_print_in_hook(data->base, data->pos, fmt, ##__VA_ARGS__);\
- data->pos += _written;\
- _written;\
-})
-
-#endif
-
-/**
- * Callback function type for printf hooks.
- *
- * @param data hook data, to pass to print_in_hook()
- * @param spec format specifier
- * @param args arguments array
- * @return number of characters written
- */
-typedef int (*printf_hook_function_t)(printf_hook_data_t *data,
- printf_hook_spec_t *spec,
- const void *const *args);
-
-/**
- * Properties of the format specifier
- */
-struct printf_hook_spec_t {
- /**
- * TRUE if a '#' was used in the format specifier
- */
- int hash;
-
- /**
- * TRUE if a '-' was used in the format specifier
- */
- int minus;
-
- /**
- * TRUE if a '+' was used in the format specifier
- */
- int plus;
-
- /**
- * The width as given in the format specifier.
- */
- int width;
-};
-
-/**
- * Printf handler management.
- */
-struct printf_hook_t {
-
- /**
- * Register a printf handler.
- *
- * @param spec printf hook format character
- * @param hook hook function
- * @param ... list of PRINTF_HOOK_ARGTYPE_*, MUST end with PRINTF_HOOK_ARGTYPE_END
- */
- void (*add_handler)(printf_hook_t *this, char spec,
- printf_hook_function_t hook, ...);
-
- /**
- * Destroy a printf_hook instance.
- */
- void (*destroy)(printf_hook_t *this);
-};
-
-/**
- * Create a printf_hook instance.
- */
-printf_hook_t *printf_hook_create();
-
-#endif /** PRINTF_HOOK_H_ @}*/
diff --git a/src/libstrongswan/utils/printf_hook/printf_hook.h b/src/libstrongswan/utils/printf_hook/printf_hook.h
new file mode 100644
index 000000000..c1d6fa90d
--- /dev/null
+++ b/src/libstrongswan/utils/printf_hook/printf_hook.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2009 Tobias Brunner
+ * Copyright (C) 2006-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup printf_hook printf_hook
+ * @{ @ingroup utils
+ */
+
+#ifndef PRINTF_HOOK_H_
+#define PRINTF_HOOK_H_
+
+#include <stdlib.h>
+
+typedef struct printf_hook_t printf_hook_t;
+typedef struct printf_hook_spec_t printf_hook_spec_t;
+typedef struct printf_hook_data_t printf_hook_data_t;
+typedef enum printf_hook_argtype_t printf_hook_argtype_t;
+
+#if defined(USE_VSTR)
+# include "printf_hook_vstr.h"
+#elif defined(USE_BUILTIN_PRINTF)
+# include "printf_hook_builtin.h"
+#endif
+
+/**
+ * Argument types to pass to printf hook.
+ */
+enum printf_hook_argtype_t {
+ PRINTF_HOOK_ARGTYPE_END,
+ PRINTF_HOOK_ARGTYPE_INT,
+ PRINTF_HOOK_ARGTYPE_POINTER,
+};
+
+/**
+ * Callback function type for printf hooks.
+ *
+ * @param data hook data, to pass to print_in_hook()
+ * @param spec format specifier
+ * @param args arguments array
+ * @return number of characters written
+ */
+typedef int (*printf_hook_function_t)(printf_hook_data_t *data,
+ printf_hook_spec_t *spec,
+ const void *const *args);
+
+/**
+ * Properties of the format specifier
+ */
+struct printf_hook_spec_t {
+
+ /**
+ * TRUE if a '#' was used in the format specifier
+ */
+ int hash;
+
+ /**
+ * TRUE if a '-' was used in the format specifier
+ */
+ int minus;
+
+ /**
+ * TRUE if a '+' was used in the format specifier
+ */
+ int plus;
+
+ /**
+ * The width as given in the format specifier.
+ */
+ int width;
+};
+
+/**
+ * Printf handler management.
+ */
+struct printf_hook_t {
+
+ /**
+ * Register a printf handler.
+ *
+ * @param spec printf hook format character
+ * @param hook hook function
+ * @param ... list of PRINTF_HOOK_ARGTYPE_*, MUST end with PRINTF_HOOK_ARGTYPE_END
+ */
+ void (*add_handler)(printf_hook_t *this, char spec,
+ printf_hook_function_t hook, ...);
+
+ /**
+ * Destroy a printf_hook instance.
+ */
+ void (*destroy)(printf_hook_t *this);
+};
+
+/**
+ * Create a printf_hook instance.
+ */
+printf_hook_t *printf_hook_create();
+
+/**
+ * Print with format string within a printf hook.
+ *
+ * @param data hook data, as passed to printf hook
+ * @param fmt printf format string
+ * @param ... arguments to format string
+ * @return number of characters written
+ */
+size_t print_in_hook(printf_hook_data_t *data, char *fmt, ...);
+
+#endif /** PRINTF_HOOK_H_ @}*/
diff --git a/src/libstrongswan/utils/printf_hook/printf_hook_builtin.c b/src/libstrongswan/utils/printf_hook/printf_hook_builtin.c
new file mode 100644
index 000000000..d00abef20
--- /dev/null
+++ b/src/libstrongswan/utils/printf_hook/printf_hook_builtin.c
@@ -0,0 +1,1168 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * Copyright (C) 2002-2006 H. Peter Anvin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "printf_hook.h"
+
+#include <utils/utils.h>
+#include <utils/debug.h>
+#include <collections/hashtable.h>
+
+#include <inttypes.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+
+#define PRINTF_BUF_LEN 8192
+#define ARGS_MAX 3
+
+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
+ */
+ int argtypes[ARGS_MAX];
+};
+
+/**
+ * Data to pass to a printf hook.
+ */
+struct printf_hook_data_t {
+
+ /**
+ * Output buffer
+ */
+ char *q;
+
+ /**
+ * Remaining bytes in q
+ */
+ size_t n;
+};
+
+/**
+ * Registered hooks (char => printf_hook_handler_t)
+ */
+static hashtable_t *hooks;
+
+/**
+ * builtin-printf variant of print_in_hook()
+ */
+size_t print_in_hook(printf_hook_data_t *data, char *fmt, ...)
+{
+ int written;
+ va_list args;
+
+ va_start(args, fmt);
+ written = builtin_vsnprintf(data->q, data->n, fmt, args);
+ va_end(args);
+
+ if (written > data->n)
+ {
+ written = data->n;
+ }
+ data->q += written;
+ data->n += written;
+ return written;
+}
+
+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;
+
+ 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;
+ }
+ handler->argtypes[i] = argtype;
+ }
+ va_end(args);
+
+ handler->numargs = i + 1;
+ if (!failed && handler->numargs > 0)
+ {
+ free(hooks->put(hooks, (void*)(uintptr_t)spec, handler));
+ }
+ else
+ {
+ free(handler);
+ }
+}
+
+/**
+ * Printf format modifier flags
+ */
+typedef enum {
+ FL_ZERO = 0x01,
+ FL_MINUS = 0x02,
+ FL_PLUS = 0x04,
+ FL_TICK = 0x08,
+ FL_SPACE = 0x10,
+ FL_HASH = 0x20,
+ FL_SIGNED = 0x40,
+ FL_UPPER = 0x80,
+} bpf_flag_t;
+
+/**
+ * Size of format string arguments
+ */
+typedef enum {
+ RNK_CHAR = -2,
+ RNK_SHORT = -1,
+ RNK_INT = 0,
+ RNK_LONG = 1,
+ RNK_LONGLONG = 2,
+
+ RNK_INTMAX = RNK_LONGLONG,
+ RNK_SIZE_T = RNK_LONG,
+ RNK_PTRDIFF_T = RNK_LONG,
+
+ RNK_MIN = RNK_CHAR,
+ RNK_MAX = RNK_LONGLONG,
+} bpf_rank_t;
+
+/**
+ * Printf specifier Parser state
+ */
+typedef enum {
+ /* Ground state */
+ ST_NORMAL,
+ /* Special flags */
+ ST_FLAGS,
+ /* Field width */
+ ST_WIDTH,
+ /* Field precision */
+ ST_PREC,
+ /* Length or conversion modifiers */
+ ST_MODIFIERS,
+} bpf_state_t;
+
+#define EMIT(x) ({ if (o<n){*q++ = (x);} o++; })
+
+static const char lcdigits[] = "0123456789abcdef";
+static const char ucdigits[] = "0123456789ABCDEF";
+
+/**
+ * Write an integer argument to q, using flags, base, width and precision
+ */
+static size_t format_int(char *q, size_t n, uintmax_t val, bpf_flag_t flags,
+ int base, int width, int prec)
+{
+ char *qq;
+ size_t o = 0, oo;
+ const char *digits;
+ uintmax_t tmpval;
+ int minus = 0;
+ int ndigits = 0, nchars;
+ int tickskip, b4tick;
+
+ /* Select type of digits */
+ digits = (flags & FL_UPPER) ? ucdigits : lcdigits;
+
+ /* If signed, separate out the minus */
+ if (flags & FL_SIGNED && (intmax_t) val < 0)
+ {
+ minus = 1;
+ val = (uintmax_t) (-(intmax_t) val);
+ }
+
+ /* Count the number of digits needed. This returns zero for 0. */
+ tmpval = val;
+ while (tmpval)
+ {
+ tmpval /= base;
+ ndigits++;
+ }
+
+ /* Adjust ndigits for size of output */
+ if (flags & FL_HASH && base == 8)
+ {
+ if (prec < ndigits + 1)
+ {
+ prec = ndigits + 1;
+ }
+ }
+
+ if (ndigits < prec)
+ {
+ /* Mandatory number padding */
+ ndigits = prec;
+ }
+ else if (val == 0)
+ {
+ /* Zero still requires space */
+ ndigits = 1;
+ }
+
+ /* For ', figure out what the skip should be */
+ if (flags & FL_TICK)
+ {
+ if (base == 16)
+ {
+ tickskip = 4;
+ }
+ else
+ {
+ tickskip = 3;
+ }
+ }
+ else
+ {
+ /* No tick marks */
+ tickskip = ndigits;
+ }
+
+ /* Tick marks aren't digits, but generated by the number converter */
+ ndigits += (ndigits - 1) / tickskip;
+
+ /* Now compute the number of nondigits */
+ nchars = ndigits;
+
+ if (minus || (flags & (FL_PLUS | FL_SPACE)))
+ {
+ /* Need space for sign */
+ nchars++;
+ }
+ if ((flags & FL_HASH) && base == 16)
+ {
+ /* Add 0x for hex */
+ nchars += 2;
+ }
+
+ /* Emit early space padding */
+ if (!(flags & (FL_MINUS | FL_ZERO)) && width > nchars)
+ {
+ while (width > nchars)
+ {
+ EMIT(' ');
+ width--;
+ }
+ }
+
+ /* Emit nondigits */
+ if (minus)
+ {
+ EMIT('-');
+ }
+ else if (flags & FL_PLUS)
+ {
+ EMIT('+');
+ }
+ else if (flags & FL_SPACE)
+ {
+ EMIT(' ');
+ }
+
+ if ((flags & FL_HASH) && base == 16)
+ {
+ EMIT('0');
+ EMIT((flags & FL_UPPER) ? 'X' : 'x');
+ }
+
+ /* Emit zero padding */
+ if ((flags & (FL_MINUS | FL_ZERO)) == FL_ZERO && width > ndigits)
+ {
+ while (width > nchars)
+ {
+ EMIT('0');
+ width--;
+ }
+ }
+
+ /* Generate the number. This is done from right to left. */
+ /* Advance the pointer to end of number */
+ q += ndigits;
+ o += ndigits;
+ /* Temporary values */
+ qq = q;
+ oo = o;
+
+ b4tick = tickskip;
+ while (ndigits > 0)
+ {
+ if (!b4tick--)
+ {
+ qq--;
+ oo--;
+ ndigits--;
+ if (oo < n)
+ {
+ *qq = '_';
+ }
+ b4tick = tickskip - 1;
+ }
+ qq--;
+ oo--;
+ ndigits--;
+ if (oo < n)
+ {
+ *qq = digits[val % base];
+ }
+ val /= base;
+ }
+
+ /* Emit late space padding */
+ while ((flags & FL_MINUS) && width > nchars)
+ {
+ EMIT(' ');
+ width--;
+ }
+
+ return o;
+}
+
+/**
+ * Write an double argument to q, using flags, base, width and precision
+ */
+static size_t format_double(char *q, size_t n, double val, bpf_flag_t flags,
+ int base, int width, int prec)
+{
+ char *qq;
+ size_t o = 0, oo;
+ const char *digits;
+ uintmax_t tmpval;
+ int minus = 0;
+ int ndigits = 0, nchars;
+
+ /* Select type of digits */
+ digits = (flags & FL_UPPER) ? ucdigits : lcdigits;
+
+ if (prec < 0)
+ {
+ /* default precision */
+ prec = 6;
+ }
+ if (val < 0)
+ {
+ minus = 1;
+ }
+
+ tmpval = (uintmax_t)fabs(val);
+ while (tmpval)
+ {
+ tmpval /= base;
+ ndigits++;
+ }
+ if (val == 0)
+ {
+ ndigits++;
+ }
+
+ /* Now compute the number of nondigits */
+ nchars = ndigits;
+
+ if (prec)
+ {
+ /* Space for decimal-point and digits after that */
+ nchars += prec + 1;
+ }
+ if (minus || (flags & (FL_PLUS | FL_SPACE)))
+ {
+ /* Need space for sign */
+ nchars++;
+ }
+ if ((flags & FL_HASH) && base == 16)
+ {
+ /* Add 0x for hex */
+ nchars += 2;
+ }
+
+ /* Emit early space padding */
+ if (!(flags & (FL_MINUS | FL_ZERO)) && width > nchars)
+ {
+ while (width > nchars)
+ {
+ EMIT(' ');
+ width--;
+ }
+ }
+
+ /* Emit nondigits */
+ if (minus)
+ {
+ EMIT('-');
+ }
+ else if (flags & FL_PLUS)
+ {
+ EMIT('+');
+ }
+ else if (flags & FL_SPACE)
+ {
+ EMIT(' ');
+ }
+
+ if ((flags & FL_HASH) && base == 16)
+ {
+ EMIT('0');
+ EMIT((flags & FL_UPPER) ? 'X' : 'x');
+ }
+
+ /* Emit zero padding */
+ if ((flags & (FL_MINUS | FL_ZERO)) == FL_ZERO && width > ndigits)
+ {
+ while (width > nchars)
+ {
+ EMIT('0');
+ width--;
+ }
+ }
+
+ /* Generate the number. This is done from right to left. */
+ /* Advance the pointer to end of number */
+ q += ndigits;
+ o += ndigits;
+ /* Temporary values */
+ qq = q;
+ oo = o;
+
+ tmpval = (uintmax_t)fabs(val);
+ if (!prec)
+ {
+ /* round up if no additional digits */
+ if (fabs(val) - tmpval >= 0.5)
+ {
+ tmpval++;
+ }
+ }
+ while (ndigits > 0)
+ {
+ qq--;
+ oo--;
+ ndigits--;
+ if (oo < n)
+ {
+ *qq = digits[tmpval % base];
+ }
+ tmpval /= base;
+ }
+
+ if (prec)
+ {
+ EMIT('.');
+
+ q += prec;
+ o += prec;
+ qq = q;
+ oo = o;
+
+ tmpval = (uintmax_t)(fabs(val) * pow(base, prec));
+ /* round up if required */
+ if (fabs(val) * pow(base, prec) - tmpval >= 0.5)
+ {
+ tmpval++;
+ }
+ while (prec > 0)
+ {
+ qq--;
+ oo--;
+ prec--;
+ if (oo < n)
+ {
+ *qq = digits[tmpval % base];
+ }
+ tmpval /= base;
+ }
+ }
+
+ /* Emit late space padding */
+ while ((flags & FL_MINUS) && width > nchars)
+ {
+ EMIT(' ');
+ width--;
+ }
+
+ return o;
+}
+
+int builtin_vsnprintf(char *buffer, size_t n, const char *format, va_list ap)
+{
+ const char *p = format;
+ char ch;
+ char *q = buffer;
+ /* Number of characters output */
+ size_t o = 0;
+ uintmax_t val = 0;
+ /* Default rank */
+ int rank = RNK_INT;
+ int width = 0;
+ int prec = -1;
+ int base;
+ size_t sz;
+ bpf_flag_t flags = 0;
+ bpf_state_t state = ST_NORMAL;
+ /* %s string argument */
+ const char *sarg;
+ /* %c char argument */
+ char carg;
+ /* String length */
+ int slen;
+
+ while ((ch = *p++))
+ {
+ switch (state)
+ {
+ case ST_NORMAL:
+ {
+ if (ch == '%')
+ {
+ state = ST_FLAGS;
+ flags = 0;
+ rank = RNK_INT;
+ width = 0;
+ prec = -1;
+ }
+ else
+ {
+ EMIT(ch);
+ }
+ break;
+ }
+ case ST_FLAGS:
+ {
+ switch (ch)
+ {
+ case '-':
+ flags |= FL_MINUS;
+ break;
+ case '+':
+ flags |= FL_PLUS;
+ break;
+ case '\'':
+ flags |= FL_TICK;
+ break;
+ case ' ':
+ flags |= FL_SPACE;
+ break;
+ case '#':
+ flags |= FL_HASH;
+ break;
+ case '0':
+ flags |= FL_ZERO;
+ break;
+ default:
+ state = ST_WIDTH;
+ /* Process this character again */
+ p--;
+ break;
+ }
+ break;
+ }
+ case ST_WIDTH:
+ {
+ if (ch >= '0' && ch <= '9')
+ {
+ width = width * 10 + (ch - '0');
+ }
+ else if (ch == '*')
+ {
+ width = va_arg(ap, int);
+ if (width < 0)
+ {
+ width = -width;
+ flags |= FL_MINUS;
+ }
+ }
+ else if (ch == '.')
+ {
+ /* Precision given */
+ prec = 0;
+ state = ST_PREC;
+ }
+ else
+ {
+ state = ST_MODIFIERS;
+ /* Process this character again */
+ p--;
+ }
+ break;
+ }
+ case ST_PREC:
+ {
+ if (ch >= '0' && ch <= '9')
+ {
+ prec = prec * 10 + (ch - '0');
+ }
+ else if (ch == '*')
+ {
+ prec = va_arg(ap, int);
+ if (prec < 0)
+ {
+ prec = -1;
+ }
+ }
+ else
+ {
+ state = ST_MODIFIERS;
+ /* Process this character again */
+ p--;
+ }
+ break;
+ }
+ case ST_MODIFIERS:
+ {
+ switch (ch)
+ {
+ /* Length modifiers - nonterminal sequences */
+ case 'h':
+ rank--;
+ break;
+ case 'l':
+ rank++;
+ break;
+ case 'j':
+ rank = RNK_INTMAX;
+ break;
+ case 'z':
+ rank = RNK_SIZE_T;
+ break;
+ case 't':
+ rank = RNK_PTRDIFF_T;
+ break;
+ case 'L':
+ case 'q':
+ rank += 2;
+ break;
+ default:
+ {
+ /* Output modifiers - terminal sequences */
+
+ /* Next state will be normal */
+ state = ST_NORMAL;
+
+ /* Canonicalize rank */
+ if (rank < RNK_MIN)
+ {
+ rank = RNK_MIN;
+ }
+ else if (rank > RNK_MAX)
+ {
+ rank = RNK_MAX;
+ }
+
+ switch (ch)
+ {
+ case 'P':
+ {
+ /* Upper case pointer */
+ flags |= FL_UPPER;
+ /* fall through */
+ }
+ case 'p':
+ {
+ /* Pointer */
+ base = 16;
+ prec = (CHAR_BIT*sizeof(void *)+3)/4;
+ flags |= FL_HASH;
+ val = (uintmax_t)(uintptr_t)
+ va_arg(ap, void *);
+ goto is_integer;
+ }
+ case 'd':
+ case 'i':
+ {
+ /* Signed decimal output */
+ base = 10;
+ flags |= FL_SIGNED;
+ switch (rank)
+ {
+ case RNK_CHAR:
+ /* Yes, all these casts are
+ needed... */
+ val = (uintmax_t)(intmax_t)(signed char)
+ va_arg(ap, signed int);
+ break;
+ case RNK_SHORT:
+ val = (uintmax_t)(intmax_t)(signed short)
+ va_arg(ap, signed int);
+ break;
+ case RNK_INT:
+ val = (uintmax_t)(intmax_t)
+ va_arg(ap, signed int);
+ break;
+ case RNK_LONG:
+ val = (uintmax_t)(intmax_t)
+ va_arg(ap, signed long);
+ break;
+ case RNK_LONGLONG:
+ val = (uintmax_t)(intmax_t)
+ va_arg(ap, signed long long);
+ break;
+ }
+ goto is_integer;
+ }
+ case 'o':
+ {
+ /* Octal */
+ base = 8;
+ goto is_unsigned;
+ }
+ case 'u':
+ {
+ /* Unsigned decimal */
+ base = 10;
+ goto is_unsigned;
+ }
+ case 'X':
+ {
+ /* Upper case hexadecimal */
+ flags |= FL_UPPER;
+ /* fall through */
+ }
+ case 'x':
+ {
+ /* Hexadecimal */
+ base = 16;
+ goto is_unsigned;
+ }
+ is_unsigned:
+ {
+ switch (rank) {
+ case RNK_CHAR:
+ val = (uintmax_t)(unsigned char)
+ va_arg(ap, unsigned int);
+ break;
+ case RNK_SHORT:
+ val = (uintmax_t)(unsigned short)
+ va_arg(ap, unsigned int);
+ break;
+ case RNK_INT:
+ val = (uintmax_t)
+ va_arg(ap, unsigned int);
+ break;
+ case RNK_LONG:
+ val = (uintmax_t)
+ va_arg(ap, unsigned long);
+ break;
+ case RNK_LONGLONG:
+ val = (uintmax_t)
+ va_arg(ap, unsigned long long);
+ break;
+ }
+ goto is_integer;
+ }
+ is_integer:
+ {
+ sz = format_int(q, (o < n) ? n - o : 0,
+ val, flags, base, width, prec);
+ q += sz;
+ o += sz;
+ break;
+ }
+ case 'c':
+ {
+ /* Character */
+ carg = (char)va_arg(ap, int);
+ sarg = &carg;
+ slen = 1;
+ goto is_string;
+ }
+ case 's':
+ {
+ /* String */
+ sarg = va_arg(ap, const char *);
+ sarg = sarg ? sarg : "(null)";
+ slen = strlen(sarg);
+ goto is_string;
+ }
+ case 'm':
+ {
+ /* glibc error string */
+ sarg = strerror(errno);
+ slen = strlen(sarg);
+ goto is_string;
+ }
+ is_string:
+ {
+ char sch;
+ int i;
+
+ if (prec != -1 && slen > prec)
+ {
+ slen = prec;
+ }
+
+ if (width > slen && !(flags & FL_MINUS))
+ {
+ char pad = (flags & FL_ZERO) ? '0' : ' ';
+ while (width > slen)
+ {
+ EMIT(pad);
+ width--;
+ }
+ }
+ for (i = slen; i; i--)
+ {
+ sch = *sarg++;
+ EMIT(sch);
+ }
+ if (width > slen && (flags & FL_MINUS))
+ {
+ while (width > slen)
+ {
+ EMIT(' ');
+ width--;
+ }
+ }
+ break;
+ }
+ case 'A':
+ {
+ base = 16;
+ flags |= FL_UPPER;
+ goto is_double;
+ }
+ case 'E':
+ case 'G':
+ {
+ /* currently not supported, fall */
+ }
+ case 'F':
+ {
+ base = 10;
+ flags |= FL_UPPER;
+ goto is_double;
+ }
+ case 'a':
+ {
+ base = 16;
+ goto is_double;
+ }
+ case 'e':
+ case 'g':
+ {
+ /* currently not supported, fall */
+ }
+ case 'f':
+ {
+ base = 10;
+ goto is_double;
+ }
+ is_double:
+ {
+ double dval;
+
+ dval = va_arg(ap, double);
+ if (isinf(dval))
+ {
+ if (isgreater(dval, 0.0))
+ {
+ sarg = flags & FL_UPPER ? "INF" : "inf";
+ }
+ else
+ {
+ sarg = flags & FL_UPPER ? "-INF" : "-inf";
+ }
+ slen = strlen(sarg);
+ goto is_string;
+ }
+ if (isnan(dval))
+ {
+ sarg = flags & FL_UPPER ? "NAN" : "nan";
+ slen = strlen(sarg);
+ goto is_string;
+ }
+ sz = format_double(q, (o < n) ? n - o : 0,
+ dval, flags, base, width, prec);
+ q += sz;
+ o += sz;
+ break;
+ }
+ case 'n':
+ {
+ /* Output the number of characters written */
+ switch (rank)
+ {
+ case RNK_CHAR:
+ *va_arg(ap, signed char *) = o;
+ break;
+ case RNK_SHORT:
+ *va_arg(ap, signed short *) = o;
+ break;
+ case RNK_INT:
+ *va_arg(ap, signed int *) = o;
+ break;
+ case RNK_LONG:
+ *va_arg(ap, signed long *) = o;
+ break;
+ case RNK_LONGLONG:
+ *va_arg(ap, signed long long *) = o;
+ break;
+ }
+ break;
+ }
+ default:
+ {
+ printf_hook_handler_t *handler;
+
+ handler = hooks->get(hooks, (void*)(uintptr_t)ch);
+ if (handler)
+ {
+ const void *args[ARGS_MAX];
+ int i, iargs[ARGS_MAX];
+ void *pargs[ARGS_MAX];
+ printf_hook_spec_t spec = {
+ .hash = flags & FL_HASH,
+ .plus = flags & FL_PLUS,
+ .minus = flags & FL_MINUS,
+ .width = width,
+ };
+ printf_hook_data_t data = {
+ .q = q,
+ .n = (o < n) ? n - o : 0,
+ };
+
+ for (i = 0; i < handler->numargs; i++)
+ {
+ switch (handler->argtypes[i])
+ {
+ case PRINTF_HOOK_ARGTYPE_INT:
+ iargs[i] = va_arg(ap, int);
+ args[i] = &iargs[i];
+ break;
+ case PRINTF_HOOK_ARGTYPE_POINTER:
+ pargs[i] = va_arg(ap, void*);
+ args[i] = &pargs[i];
+ break;
+ }
+ }
+ sz = handler->hook(&data, &spec, args);
+ q += sz;
+ o += sz;
+ }
+ else
+ {
+ /* Anything else, including % */
+ EMIT(ch);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Null-terminate the string */
+ if (o < n)
+ {
+ /* No overflow */
+ *q = '\0';
+ }
+ else if (n > 0)
+ {
+ /* Overflow - terminate at end of buffer */
+ buffer[n - 1] = '\0';
+ }
+ return o;
+}
+
+int builtin_printf(const char *format, ...)
+{
+ int written;
+ va_list args;
+
+ va_start(args, format);
+ written = builtin_vprintf(format, args);
+ va_end(args);
+
+ return written;
+}
+
+int builtin_fprintf(FILE *stream, const char *format, ...)
+{
+ int written;
+ va_list args;
+
+ va_start(args, format);
+ written = builtin_vfprintf(stream, format, args);
+ va_end(args);
+
+ return written;
+}
+
+int builtin_sprintf(char *str, const char *format, ...)
+{
+ int written;
+ va_list args;
+
+ va_start(args, format);
+ written = builtin_vsnprintf(str, ~(size_t)0, format, args);
+ va_end(args);
+
+ return written;
+}
+
+int builtin_snprintf(char *str, size_t size, const char *format, ...)
+{
+ int written;
+ va_list args;
+
+ va_start(args, format);
+ written = builtin_vsnprintf(str, size, format, args);
+ va_end(args);
+
+ return written;
+}
+
+int builtin_asprintf(char **str, const char *format, ...)
+{
+ int written;
+ va_list args;
+
+ va_start(args, format);
+ written = builtin_vasprintf(str, format, args);
+ va_end(args);
+
+ return written;
+}
+
+int builtin_vprintf(const char *format, va_list ap)
+{
+ return builtin_vfprintf(stdout, format, ap);
+}
+
+int builtin_vfprintf(FILE *stream, const char *format, va_list ap)
+{
+ char buf[PRINTF_BUF_LEN];
+ int len;
+
+ len = builtin_vsnprintf(buf, sizeof(buf), format, ap);
+ return fwrite(buf, 1, len, stream);
+}
+
+int builtin_vsprintf(char *str, const char *format, va_list ap)
+{
+ return builtin_vsnprintf(str, ~(size_t)0, format, ap);
+}
+
+int builtin_vasprintf(char **str, const char *format, va_list ap)
+{
+ char buf[PRINTF_BUF_LEN];
+ int len;
+
+ len = builtin_vsnprintf(buf, sizeof(buf), format, ap);
+ *str = strdup(buf);
+ return len;
+}
+
+METHOD(printf_hook_t, destroy, void,
+ private_printf_hook_t *this)
+{
+ enumerator_t *enumerator;
+ printf_hook_handler_t *handler;
+
+ enumerator = hooks->create_enumerator(hooks);
+ while (enumerator->enumerate(enumerator, NULL, &handler))
+ {
+ free(handler);
+ }
+ enumerator->destroy(enumerator);
+
+ hooks->destroy(hooks);
+
+ 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,
+ },
+ );
+
+ hooks = hashtable_create(hashtable_hash_ptr, hashtable_equals_ptr, 8);
+
+ return &this->public;
+}
diff --git a/src/libstrongswan/utils/printf_hook/printf_hook_builtin.h b/src/libstrongswan/utils/printf_hook/printf_hook_builtin.h
new file mode 100644
index 000000000..409b5bf3d
--- /dev/null
+++ b/src/libstrongswan/utils/printf_hook/printf_hook_builtin.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup printf_hook_builtin printf_hook_builtin
+ * @{ @ingroup utils
+ */
+
+#ifndef PRINTF_HOOK_BUILTIN_H_
+#define PRINTF_HOOK_BUILTIN_H_
+
+#include <stdarg.h>
+#include <stdio.h>
+
+int builtin_printf(const char *format, ...);
+int builtin_fprintf(FILE *stream, const char *format, ...);
+int builtin_sprintf(char *str, const char *format, ...);
+int builtin_snprintf(char *str, size_t size, const char *format, ...);
+int builtin_asprintf(char **str, const char *format, ...);
+
+int builtin_vprintf(const char *format, va_list ap);
+int builtin_vfprintf(FILE *stream, const char *format, va_list ap);
+int builtin_vsprintf(char *str, const char *format, va_list ap);
+int builtin_vsnprintf(char *str, size_t size, const char *format, va_list ap);
+int builtin_vasprintf(char **str, const char *format, va_list ap);
+
+#ifdef printf
+#undef printf
+#endif
+#ifdef fprintf
+#undef fprintf
+#endif
+#ifdef sprintf
+#undef sprintf
+#endif
+#ifdef snprintf
+#undef snprintf
+#endif
+#ifdef asprintf
+#undef asprintf
+#endif
+#ifdef vprintf
+#undef vprintf
+#endif
+#ifdef vfprintf
+#undef vfprintf
+#endif
+#ifdef vsprintf
+#undef vsprintf
+#endif
+#ifdef vsnprintf
+#undef vsnprintf
+#endif
+#ifdef vasprintf
+#undef vasprintf
+#endif
+
+#define printf builtin_printf
+#define fprintf builtin_fprintf
+#define sprintf builtin_sprintf
+#define snprintf builtin_snprintf
+#define asprintf builtin_asprintf
+
+#define vprintf builtin_vprintf
+#define vfprintf builtin_vfprintf
+#define vsprintf builtin_vsprintf
+#define vsnprintf builtin_vsnprintf
+#define vasprintf builtin_vasprintf
+
+#endif /** PRINTF_HOOK_BUILTIN_H_ @}*/
diff --git a/src/libstrongswan/utils/printf_hook/printf_hook_glibc.c b/src/libstrongswan/utils/printf_hook/printf_hook_glibc.c
new file mode 100644
index 000000000..8fd1aed4a
--- /dev/null
+++ b/src/libstrongswan/utils/printf_hook/printf_hook_glibc.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2009-2013 Tobias Brunner
+ * Copyright (C) 2006-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "printf_hook.h"
+
+#include <utils/utils.h>
+#include <utils/debug.h>
+
+#include <printf.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+typedef struct private_printf_hook_t private_printf_hook_t;
+typedef struct printf_hook_handler_t printf_hook_handler_t;
+
+/**
+ * private data of printf_hook
+ */
+struct private_printf_hook_t {
+
+ /**
+ * public functions
+ */
+ printf_hook_t public;
+};
+
+/**
+ * struct with information about a registered handler
+ */
+struct printf_hook_handler_t {
+
+ /**
+ * callback function
+ */
+ printf_hook_function_t hook;
+
+ /**
+ * number of arguments
+ */
+ int numargs;
+
+ /**
+ * types of the arguments, PA_*
+ */
+ int argtypes[3];
+};
+
+/**
+ * Data to pass to a printf hook.
+ */
+struct printf_hook_data_t {
+
+ /**
+ * Output FILE stream
+ */
+ FILE *stream;;
+};
+
+/* A-Z | 6 other chars | a-z */
+static printf_hook_handler_t *printf_hooks[58];
+
+#define SPEC_TO_INDEX(spec) ((int)(spec) - (int)'A')
+
+/**
+ * Glibc variant of print_in_hook()
+ */
+size_t print_in_hook(printf_hook_data_t *data, char *fmt, ...)
+{
+ ssize_t written;
+ va_list args;
+
+ va_start(args, fmt);
+ written = vfprintf(data->stream, fmt, args);
+ va_end(args);
+
+ if (written < 0)
+ {
+ written = 0;
+ }
+ return written;
+}
+
+/**
+ * Printf hook print function. This is actually of type "printf_function",
+ * however glibc does it typedef to function, but uclibc to a pointer.
+ * So we redefine it here.
+ */
+static int custom_print(FILE *stream, const struct printf_info *info,
+ const void *const *args)
+{
+ printf_hook_spec_t spec;
+ printf_hook_handler_t *handler;
+ printf_hook_data_t data = {
+ .stream = stream,
+ };
+
+ handler = printf_hooks[SPEC_TO_INDEX(info->spec)];
+ spec.hash = info->alt;
+ spec.plus = info->showsign;
+ spec.minus = info->left;
+ spec.width = info->width;
+
+ return handler->hook(&data, &spec, args);
+}
+
+/**
+ * Printf hook arginfo function, which is actually of type
+ * "printf_arginfo_[size_]function".
+ */
+static int custom_arginfo(const struct printf_info *info, size_t n, int *argtypes
+#ifdef HAVE_PRINTF_SPECIFIER
+ , int *size
+#endif
+ )
+{
+ int i;
+ printf_hook_handler_t *handler;
+
+ handler = printf_hooks[SPEC_TO_INDEX(info->spec)];
+ if (handler->numargs <= n)
+ {
+ for (i = 0; i < handler->numargs; ++i)
+ {
+ argtypes[i] = handler->argtypes[i];
+ }
+ }
+ /* we never set "size", as we have no user defined types */
+ return handler->numargs;
+}
+
+METHOD(printf_hook_t, add_handler, void,
+ private_printf_hook_t *this, char spec,
+ printf_hook_function_t hook, ...)
+{
+ int i = -1;
+ bool failed = FALSE;
+ printf_hook_handler_t *handler;
+ printf_hook_argtype_t argtype;
+ va_list args;
+
+ if (SPEC_TO_INDEX(spec) <= -1 ||
+ SPEC_TO_INDEX(spec) >= countof(printf_hooks))
+ {
+ DBG1(DBG_LIB, "'%c' is not a valid printf hook specifier, "
+ "not registered!", spec);
+ return;
+ }
+
+ INIT(handler,
+ .hook = hook,
+ );
+
+ va_start(args, hook);
+ while (!failed)
+ {
+ argtype = va_arg(args, printf_hook_argtype_t);
+
+ if (argtype == PRINTF_HOOK_ARGTYPE_END)
+ {
+ break;
+ }
+ if (++i >= countof(handler->argtypes))
+ {
+ DBG1(DBG_LIB, "Too many arguments for printf hook with "
+ "specifier '%c', not registered!", spec);
+ failed = TRUE;
+ break;
+ }
+ switch (argtype)
+ {
+ case PRINTF_HOOK_ARGTYPE_INT:
+ handler->argtypes[i] = PA_INT;
+ break;
+ case PRINTF_HOOK_ARGTYPE_POINTER:
+ handler->argtypes[i] = PA_POINTER;
+ break;
+ default:
+ DBG1(DBG_LIB, "Invalid printf hook arg type for '%c'", spec);
+ failed = TRUE;
+ break;
+ }
+ }
+ va_end(args);
+
+ handler->numargs = i + 1;
+ if (!failed && handler->numargs > 0)
+ {
+# ifdef HAVE_PRINTF_SPECIFIER
+ register_printf_specifier(spec, custom_print, custom_arginfo);
+# else
+ register_printf_function(spec, custom_print, custom_arginfo);
+# endif
+ printf_hooks[SPEC_TO_INDEX(spec)] = handler;
+ }
+ else
+ {
+ free(handler);
+ }
+}
+
+METHOD(printf_hook_t, destroy, void,
+ private_printf_hook_t *this)
+{
+ int i;
+
+ for (i = 0; i < countof(printf_hooks); i++)
+ {
+ free(printf_hooks[i]);
+ }
+ free(this);
+}
+
+/*
+ * see header file
+ */
+printf_hook_t *printf_hook_create()
+{
+ private_printf_hook_t *this;
+
+ INIT(this,
+ .public = {
+ .add_handler = _add_handler,
+ .destroy = _destroy,
+ },
+ );
+
+ memset(printf_hooks, 0, sizeof(printf_hooks));
+
+ return &this->public;
+}
diff --git a/src/libstrongswan/utils/printf_hook.c b/src/libstrongswan/utils/printf_hook/printf_hook_vstr.c
index f030f45c8..ab93b24ba 100644
--- a/src/libstrongswan/utils/printf_hook.c
+++ b/src/libstrongswan/utils/printf_hook/printf_hook_vstr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Tobias Brunner
+ * Copyright (C) 2009-2013 Tobias Brunner
* Copyright (C) 2006-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -16,12 +16,14 @@
#include "printf_hook.h"
-#include "utils.h"
-#include "debug.h"
+#include <utils/utils.h>
+#include <utils/debug.h>
+#include <threading/thread_value.h>
-#include <stdio.h>
-#include <stdarg.h>
+#include <vstr.h>
#include <string.h>
+#include <unistd.h>
+#include <errno.h>
typedef struct private_printf_hook_t private_printf_hook_t;
typedef struct printf_hook_handler_t printf_hook_handler_t;
@@ -56,78 +58,36 @@ struct printf_hook_handler_t {
int numargs;
/**
- * types of the arguments
+ * types of the arguments, VSTR_TYPE_FMT_*
*/
int argtypes[ARGS_MAX];
-#ifdef USE_VSTR
/**
* name required for Vstr
*/
char *name;
-#endif
};
-/* A-Z | 6 other chars | a-z */
-#define NUM_HANDLERS 58
-static printf_hook_handler_t *printf_hooks[NUM_HANDLERS];
-
-#define SPEC_TO_INDEX(spec) ((int)(spec) - (int)'A')
-#define IS_VALID_SPEC(spec) (SPEC_TO_INDEX(spec) > -1 && SPEC_TO_INDEX(spec) < NUM_HANDLERS)
-
-#if !defined(USE_VSTR) && \
- (defined(HAVE_PRINTF_FUNCTION) || defined(HAVE_PRINTF_SPECIFIER))
-
/**
- * Printf hook print function. This is actually of type "printf_function",
- * however glibc does it typedef to function, but uclibc to a pointer.
- * So we redefine it here.
+ * Data to pass to a printf hook.
*/
-static int custom_print(FILE *stream, const struct printf_info *info,
- const void *const *args)
-{
- printf_hook_spec_t spec;
- printf_hook_handler_t *handler = printf_hooks[SPEC_TO_INDEX(info->spec)];
- printf_hook_data_t data = {
- .stream = stream,
- };
-
- spec.hash = info->alt;
- spec.plus = info->showsign;
- spec.minus = info->left;
- spec.width = info->width;
-
- return handler->hook(&data, &spec, args);
-}
+struct printf_hook_data_t {
-/**
- * Printf hook arginfo function, which is actually of type
- * "printf_arginfo_[size_]function".
- */
-static int custom_arginfo(const struct printf_info *info, size_t n, int *argtypes
-#ifdef HAVE_PRINTF_SPECIFIER
- , int *size
-#endif
- )
-{
- int i;
- printf_hook_handler_t *handler = printf_hooks[SPEC_TO_INDEX(info->spec)];
+ /**
+ * Base to append printf to
+ */
+ Vstr_base *base;
- if (handler->numargs <= n)
- {
- for (i = 0; i < handler->numargs; ++i)
- {
- argtypes[i] = handler->argtypes[i];
- }
- }
- /* we never set "size", as we have no user defined types */
- return handler->numargs;
-}
+ /**
+ * Position in base to write to
+ */
+ size_t pos;
+};
-#else
+/* A-Z | 6 other chars | a-z */
+static printf_hook_handler_t *printf_hooks[58];
-#include <errno.h>
-#include <unistd.h> /* for STDOUT_FILENO */
+#define SPEC_TO_INDEX(spec) ((int)(spec) - (int)'A')
/**
* These are used below, whenever the public wrapper functions are called before
@@ -138,6 +98,22 @@ static int custom_arginfo(const struct printf_info *info, size_t n, int *argtype
#undef vsnprintf
/**
+ * Vstr variant of print_in_hook()
+ */
+size_t print_in_hook(printf_hook_data_t *data, char *fmt, ...)
+{
+ size_t written;
+ va_list args;
+
+ va_start(args, fmt);
+ written = vstr_add_vfmt(data->base, data->pos, fmt, args);
+ va_end(args);
+
+ data->pos += written;
+ return written;
+}
+
+/**
* Vstr custom format specifier callback function.
*/
static int custom_fmt_cb(Vstr_base *base, size_t pos, Vstr_fmt_spec *fmt_spec)
@@ -145,20 +121,21 @@ static int custom_fmt_cb(Vstr_base *base, size_t pos, Vstr_fmt_spec *fmt_spec)
int i;
const void *args[ARGS_MAX];
printf_hook_spec_t spec;
- printf_hook_handler_t *handler = printf_hooks[SPEC_TO_INDEX(fmt_spec->name[0])];
+ printf_hook_handler_t *handler;
printf_hook_data_t data = {
.base = base,
.pos = pos,
};
+ handler = printf_hooks[SPEC_TO_INDEX(fmt_spec->name[0])];
for (i = 0; i < handler->numargs; i++)
{
- switch(handler->argtypes[i])
+ switch (handler->argtypes[i])
{
- case PRINTF_HOOK_ARGTYPE_INT:
+ case VSTR_TYPE_FMT_INT:
args[i] = VSTR_FMT_CB_ARG_PTR(fmt_spec, i);
break;
- case PRINTF_HOOK_ARGTYPE_POINTER:
+ case VSTR_TYPE_FMT_PTR_VOID:
args[i] = &VSTR_FMT_CB_ARG_PTR(fmt_spec, i);
break;
}
@@ -167,9 +144,10 @@ static int custom_fmt_cb(Vstr_base *base, size_t pos, Vstr_fmt_spec *fmt_spec)
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;
+ spec.width = fmt_spec->obj_field_width;
handler->hook(&data, &spec, args);
+
return 1;
}
@@ -178,8 +156,10 @@ static int custom_fmt_cb(Vstr_base *base, size_t pos, Vstr_fmt_spec *fmt_spec)
*/
static void vstr_fmt_add_handler(Vstr_conf *conf, printf_hook_handler_t *handler)
{
- int *at = handler->argtypes;
- switch(handler->numargs)
+ int *at;
+
+ at = handler->argtypes;
+ switch (handler->numargs)
{
case 1:
vstr_fmt_add(conf, handler->name, custom_fmt_cb, at[0],
@@ -197,34 +177,41 @@ static void vstr_fmt_add_handler(Vstr_conf *conf, printf_hook_handler_t *handler
}
/**
- * Management of thread-specific Vstr_conf objects
+ * Thread specific vstr config
*/
-#include <threading/thread_value.h>
-
static thread_value_t *vstr_conf = NULL;
+/**
+ * Create vstr config for current thread
+ */
static Vstr_conf *create_vstr_conf()
{
+ Vstr_conf *conf;
int i;
- Vstr_conf *conf = vstr_make_conf();
+
+ conf = vstr_make_conf();
vstr_cntl_conf(conf, VSTR_CNTL_CONF_SET_FMT_CHAR_ESC, '%');
vstr_cntl_conf(conf, VSTR_CNTL_CONF_SET_TYPE_GRPALLOC_CACHE,
VSTR_TYPE_CNTL_CONF_GRPALLOC_CSTR);
vstr_cntl_conf(conf, VSTR_CNTL_CONF_SET_NUM_BUF_SZ, PRINTF_BUF_LEN);
- for (i = 0; i < NUM_HANDLERS; ++i)
+
+ for (i = 0; i < countof(printf_hooks); i++)
{
- printf_hook_handler_t *handler = printf_hooks[i];
- if (handler)
+ if (printf_hooks[i])
{
- vstr_fmt_add_handler(conf, handler);
+ vstr_fmt_add_handler(conf, printf_hooks[i]);
}
}
return conf;
}
+/**
+ * Get vstr config of current thread
+ */
static inline Vstr_conf *get_vstr_conf()
{
Vstr_conf *conf = NULL;
+
if (vstr_conf)
{
conf = (Vstr_conf*)vstr_conf->get(vstr_conf);
@@ -238,21 +225,6 @@ static inline Vstr_conf *get_vstr_conf()
}
/**
- * Described in header
- */
-size_t vstr_print_in_hook(struct Vstr_base *base, size_t pos, const char *fmt,
- ...)
-{
- va_list args;
- int written;
-
- va_start(args, fmt);
- written = vstr_add_vfmt(base, pos, fmt, args);
- va_end(args);
- return written;
-}
-
-/**
* Wrapper functions for printf and alike
*/
int vstr_wrapper_printf(const char *format, ...)
@@ -264,6 +236,7 @@ int vstr_wrapper_printf(const char *format, ...)
va_end(args);
return written;
}
+
int vstr_wrapper_fprintf(FILE *stream, const char *format, ...)
{
int written;
@@ -273,6 +246,7 @@ int vstr_wrapper_fprintf(FILE *stream, const char *format, ...)
va_end(args);
return written;
}
+
int vstr_wrapper_sprintf(char *str, const char *format, ...)
{
int written;
@@ -282,6 +256,7 @@ int vstr_wrapper_sprintf(char *str, const char *format, ...)
va_end(args);
return written;
}
+
int vstr_wrapper_snprintf(char *str, size_t size, const char *format, ...)
{
int written;
@@ -291,6 +266,7 @@ int vstr_wrapper_snprintf(char *str, size_t size, const char *format, ...)
va_end(args);
return written;
}
+
int vstr_wrapper_asprintf(char **str, const char *format, ...)
{
int written;
@@ -300,56 +276,68 @@ int vstr_wrapper_asprintf(char **str, const char *format, ...)
va_end(args);
return written;
}
-static inline int vstr_wrapper_vprintf_internal(Vstr_conf *conf, int fd,
+
+static inline int vstr_wrapper_vprintf_internal(Vstr_conf *conf, FILE *stream,
const char *format,
va_list args)
{
- int written;
- Vstr_base *s = vstr_make_base(conf);
+ struct iovec *iov;
+ int iovcnt, written = 0;
+ Vstr_base *s;
+
+ s = vstr_make_base(conf);
vstr_add_vfmt(s, 0, format, args);
- written = s->len;
- while (s->len)
+ if (vstr_export_iovec_ptr_all(s, &iov, &iovcnt))
{
- if (!vstr_sc_write_fd(s, 1, s->len, fd, NULL))
+ while (iovcnt--)
{
- if (errno != EAGAIN && errno != EINTR)
+ if (iov->iov_base)
{
- written -= s->len;
- break;
+ written += fwrite(iov->iov_base, 1, iov->iov_len, stream);
}
+ iov++;
}
}
vstr_free_base(s);
return written;
}
+
int vstr_wrapper_vprintf(const char *format, va_list args)
{
- Vstr_conf *conf = get_vstr_conf();
+ Vstr_conf *conf;
+
+ conf = get_vstr_conf();
if (conf)
{
- return vstr_wrapper_vprintf_internal(conf, STDOUT_FILENO, format, args);
+ return vstr_wrapper_vprintf_internal(conf, stdout, format, args);
}
return vprintf(format, args);
}
+
int vstr_wrapper_vfprintf(FILE *stream, const char *format, va_list args)
{
- Vstr_conf *conf = get_vstr_conf();
+ Vstr_conf *conf;
+
+ conf = get_vstr_conf();
if (conf)
{
- return vstr_wrapper_vprintf_internal(conf, fileno(stream), format,
- args);
+ return vstr_wrapper_vprintf_internal(conf, stream, format, args);
}
return vfprintf(stream, format, args);
}
+
static inline int vstr_wrapper_vsnprintf_internal(char *str, size_t size,
const char *format,
va_list args)
{
- Vstr_conf *conf = get_vstr_conf();
+ Vstr_conf *conf;
+ Vstr_base *s;
+ int written;
+
+ conf = get_vstr_conf();
if (conf)
{
- int written;
- Vstr_base *s = vstr_make_base(conf);
+ s = vstr_make_base(conf);
vstr_add_vfmt(s, 0, format, args);
written = s->len;
vstr_export_cstr_buf(s, 1, s->len, str, (size > 0) ? size : s->len + 1);
@@ -358,19 +346,27 @@ static inline int vstr_wrapper_vsnprintf_internal(char *str, size_t size,
}
return vsnprintf(str, size, format, args);
}
+
int vstr_wrapper_vsprintf(char *str, const char *format, va_list args)
{
return vstr_wrapper_vsnprintf_internal(str, 0, format, args);
}
+
int vstr_wrapper_vsnprintf(char *str, size_t size, const char *format,
va_list args)
{
- return (size > 0) ? vstr_wrapper_vsnprintf_internal(str, size, format, args) : 0;
+ if (size > 0)
+ {
+ return vstr_wrapper_vsnprintf_internal(str, size, format, args);
+ }
+ return 0;
}
+
int vstr_wrapper_vasprintf(char **str, const char *format, va_list args)
{
size_t len = 100;
int written;
+
*str = malloc(len);
while (TRUE)
{
@@ -387,60 +383,68 @@ int vstr_wrapper_vasprintf(char **str, const char *format, va_list args)
}
return written;
}
-#endif
METHOD(printf_hook_t, add_handler, void,
- private_printf_hook_t *this, char spec,
- printf_hook_function_t hook, ...)
+ private_printf_hook_t *this, char spec, printf_hook_function_t hook, ...)
{
int i = -1;
+ bool failed = FALSE;
printf_hook_handler_t *handler;
printf_hook_argtype_t argtype;
va_list args;
- if (!IS_VALID_SPEC(spec))
+ if (SPEC_TO_INDEX(spec) <= -1 ||
+ SPEC_TO_INDEX(spec) >= countof(printf_hooks))
{
DBG1(DBG_LIB, "'%c' is not a valid printf hook specifier, "
"not registered!", spec);
return;
}
- handler = malloc_thing(printf_hook_handler_t);
- handler->hook = hook;
+ INIT(handler,
+ .hook = hook,
+ );
va_start(args, hook);
- while ((argtype = va_arg(args, printf_hook_argtype_t)) != PRINTF_HOOK_ARGTYPE_END)
+ while (!failed)
{
+ argtype = va_arg(args, printf_hook_argtype_t);
+ if (argtype == PRINTF_HOOK_ARGTYPE_END)
+ {
+ break;
+ }
if (++i >= ARGS_MAX)
{
DBG1(DBG_LIB, "Too many arguments for printf hook with "
"specifier '%c', not registered!", spec);
- va_end(args);
- free(handler);
- return;
+ failed = TRUE;
+ break;
+ }
+ switch (argtype)
+ {
+ case PRINTF_HOOK_ARGTYPE_INT:
+ handler->argtypes[i] = VSTR_TYPE_FMT_INT;
+ break;
+ case PRINTF_HOOK_ARGTYPE_POINTER:
+ handler->argtypes[i] = VSTR_TYPE_FMT_PTR_VOID;
+ break;
+ default:
+ DBG1(DBG_LIB, "Invalid printf hook arg type for '%c'", spec);
+ failed = TRUE;
+ break;
}
- handler->argtypes[i] = argtype;
}
va_end(args);
handler->numargs = i + 1;
- if (handler->numargs > 0)
+ if (!failed && handler->numargs > 0)
{
-#if !defined(USE_VSTR) && \
- (defined(HAVE_PRINTF_FUNCTION) || defined(HAVE_PRINTF_SPECIFIER))
-# ifdef HAVE_PRINTF_SPECIFIER
- register_printf_specifier(spec, custom_print, custom_arginfo);
-# else
- register_printf_function(spec, custom_print, custom_arginfo);
-# endif
-#else
Vstr_conf *conf = get_vstr_conf();
handler->name = malloc(2);
handler->name[0] = spec;
handler->name[1] = '\0';
vstr_fmt_add_handler(conf, handler);
-#endif
printf_hooks[SPEC_TO_INDEX(spec)] = handler;
}
else
@@ -453,29 +457,25 @@ METHOD(printf_hook_t, destroy, void,
private_printf_hook_t *this)
{
int i;
-#ifdef USE_VSTR
- Vstr_conf *conf = get_vstr_conf();
-#endif
+ Vstr_conf *conf;
+ printf_hook_handler_t *handler;
- for (i = 0; i < NUM_HANDLERS; ++i)
+ conf = get_vstr_conf();
+ for (i = 0; i < countof(printf_hooks); ++i)
{
- printf_hook_handler_t *handler = printf_hooks[i];
+ handler = printf_hooks[i];
if (handler)
{
-#ifdef USE_VSTR
vstr_fmt_del(conf, handler->name);
free(handler->name);
-#endif
free(handler);
}
}
-#ifdef USE_VSTR
/* freeing the Vstr_conf of the main thread */
vstr_conf->destroy(vstr_conf);
vstr_conf = NULL;
vstr_exit();
-#endif
free(this);
}
@@ -495,7 +495,6 @@ printf_hook_t *printf_hook_create()
memset(printf_hooks, 0, sizeof(printf_hooks));
-#ifdef USE_VSTR
if (!vstr_init())
{
DBG1(DBG_LIB, "failed to initialize Vstr library!");
@@ -503,8 +502,6 @@ printf_hook_t *printf_hook_create()
return NULL;
}
vstr_conf = thread_value_create((thread_cleanup_t)vstr_free_conf);
-#endif
return &this->public;
}
-
diff --git a/src/libstrongswan/utils/printf_hook/printf_hook_vstr.h b/src/libstrongswan/utils/printf_hook/printf_hook_vstr.h
new file mode 100644
index 000000000..2f9ee5983
--- /dev/null
+++ b/src/libstrongswan/utils/printf_hook/printf_hook_vstr.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2009 Tobias Brunner
+ * Copyright (C) 2006-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup printf_hook_vstr printf_hook_vstr
+ * @{ @ingroup utils
+ */
+
+#ifndef PRINTF_HOOK_VSTR_H_
+#define PRINTF_HOOK_VSTR_H_
+
+#include <stdarg.h>
+#include <stdio.h>
+
+int vstr_wrapper_printf(const char *format, ...);
+int vstr_wrapper_fprintf(FILE *stream, const char *format, ...);
+int vstr_wrapper_sprintf(char *str, const char *format, ...);
+int vstr_wrapper_snprintf(char *str, size_t size, const char *format, ...);
+int vstr_wrapper_asprintf(char **str, const char *format, ...);
+
+int vstr_wrapper_vprintf(const char *format, va_list ap);
+int vstr_wrapper_vfprintf(FILE *stream, const char *format, va_list ap);
+int vstr_wrapper_vsprintf(char *str, const char *format, va_list ap);
+int vstr_wrapper_vsnprintf(char *str, size_t size, const char *format, va_list ap);
+int vstr_wrapper_vasprintf(char **str, const char *format, va_list ap);
+
+#ifdef printf
+#undef printf
+#endif
+#ifdef fprintf
+#undef fprintf
+#endif
+#ifdef sprintf
+#undef sprintf
+#endif
+#ifdef snprintf
+#undef snprintf
+#endif
+#ifdef asprintf
+#undef asprintf
+#endif
+#ifdef vprintf
+#undef vprintf
+#endif
+#ifdef vfprintf
+#undef vfprintf
+#endif
+#ifdef vsprintf
+#undef vsprintf
+#endif
+#ifdef vsnprintf
+#undef vsnprintf
+#endif
+#ifdef vasprintf
+#undef vasprintf
+#endif
+
+#define printf vstr_wrapper_printf
+#define fprintf vstr_wrapper_fprintf
+#define sprintf vstr_wrapper_sprintf
+#define snprintf vstr_wrapper_snprintf
+#define asprintf vstr_wrapper_asprintf
+
+#define vprintf vstr_wrapper_vprintf
+#define vfprintf vstr_wrapper_vfprintf
+#define vsprintf vstr_wrapper_vsprintf
+#define vsnprintf vstr_wrapper_vsnprintf
+#define vasprintf vstr_wrapper_vasprintf
+
+#endif /** PRINTF_HOOK_VSTR_H_ @}*/
diff --git a/src/libstrongswan/utils/utils.c b/src/libstrongswan/utils/utils.c
index 30084cd81..266fb4357 100644
--- a/src/libstrongswan/utils/utils.c
+++ b/src/libstrongswan/utils/utils.c
@@ -29,6 +29,7 @@
#include "collections/enumerator.h"
#include "utils/debug.h"
+#include "utils/chunk.h"
ENUM(status_names, SUCCESS, NEED_MORE,
"SUCCESS",
@@ -513,6 +514,51 @@ _cas_impl(ptr, void*)
#endif /* HAVE_GCC_ATOMIC_OPERATIONS */
+
+#ifdef HAVE_FMEMOPEN_FALLBACK
+
+static int fmemread(chunk_t *cookie, char *buf, int size)
+{
+ int len;
+
+ len = min(size, cookie->len);
+ memcpy(buf, cookie->ptr, len);
+ *cookie = chunk_skip(*cookie, len);
+
+ return len;
+}
+
+static int fmemwrite(chunk_t *cookie, const char *buf, int size)
+{
+ int len;
+
+ len = min(size, cookie->len);
+ memcpy(cookie->ptr, buf, len);
+ *cookie = chunk_skip(*cookie, len);
+
+ return len;
+}
+
+static int fmemclose(void *cookie)
+{
+ free(cookie);
+ return 0;
+}
+
+FILE *fmemopen(void *buf, size_t size, const char *mode)
+{
+ chunk_t *cookie;
+
+ INIT(cookie,
+ .ptr = buf,
+ .len = size,
+ );
+
+ return funopen(cookie, (void*)fmemread, (void*)fmemwrite, NULL, fmemclose);
+}
+
+#endif /* FMEMOPEN fallback*/
+
/**
* Described in header.
*/
diff --git a/src/libstrongswan/utils/utils.h b/src/libstrongswan/utils/utils.h
index d055f712d..cda7edf08 100644
--- a/src/libstrongswan/utils/utils.h
+++ b/src/libstrongswan/utils/utils.h
@@ -113,6 +113,14 @@ static inline bool strncaseeq(const char *x, const char *y, size_t len)
}
/**
+ * Helper function that checks if a string starts with a given prefix
+ */
+static inline bool strcasepfx(const char *x, const char *prefix)
+{
+ return strncaseeq(x, prefix, strlen(prefix));
+}
+
+/**
* NULL-safe strdup variant
*/
static inline char *strdupnull(const char *s)
@@ -671,26 +679,30 @@ static inline u_int64_t untoh64(void *network)
}
/**
- * Round up size to be multiple of alignement
+ * Get the padding required to make size a multiple of alignment
*/
-static inline size_t round_up(size_t size, int alignement)
+static inline size_t pad_len(size_t size, size_t alignment)
{
- int remainder;
+ size_t remainder;
- remainder = size % alignement;
- if (remainder)
- {
- size += alignement - remainder;
- }
- return size;
+ remainder = size % alignment;
+ return remainder ? alignment - remainder : 0;
+}
+
+/**
+ * Round up size to be multiple of alignment
+ */
+static inline size_t round_up(size_t size, size_t alignment)
+{
+ return size + pad_len(size, alignment);
}
/**
- * Round down size to be a multiple of alignement
+ * Round down size to be a multiple of alignment
*/
-static inline size_t round_down(size_t size, int alignement)
+static inline size_t round_down(size_t size, size_t alignment)
{
- return size - (size % alignement);
+ return size - (size % alignment);
}
/**
@@ -753,6 +765,23 @@ bool cas_ptr(void **ptr, void *oldval, void *newval);
#endif /* HAVE_GCC_ATOMIC_OPERATIONS */
+#ifndef HAVE_FMEMOPEN
+# ifdef HAVE_FUNOPEN
+# define HAVE_FMEMOPEN
+# define HAVE_FMEMOPEN_FALLBACK
+# include <stdio.h>
+/**
+ * fmemopen(3) fallback using BSD funopen.
+ *
+ * We could also provide one using fopencookie(), but should we have it we
+ * most likely have fmemopen().
+ *
+ * fseek() is currently not supported.
+ */
+FILE *fmemopen(void *buf, size_t size, const char *mode);
+# endif /* FUNOPEN */
+#endif /* FMEMOPEN */
+
/**
* printf hook for time_t.
*