diff options
author | Gergely Nagy <algernon@balabit.hu> | 2012-07-19 13:34:49 +0200 |
---|---|---|
committer | Gergely Nagy <algernon@balabit.hu> | 2012-07-19 13:34:49 +0200 |
commit | 841f531dd0e1a95a9ce08c78b85d388806229394 (patch) | |
tree | 66fca2c17e43c02bec5c5c99cfd2b96690d4d8b8 /lib | |
parent | cd7703d466b98e9eb45df97b5d91794ef5bdeb90 (diff) | |
download | libumberlog-841f531dd0e1a95a9ce08c78b85d388806229394.tar.gz libumberlog-841f531dd0e1a95a9ce08c78b85d388806229394.tar.xz libumberlog-841f531dd0e1a95a9ce08c78b85d388806229394.zip |
Leave printf format parsing to glibc if possible.
Call glibc's parse_printf_format() to gather information about
argument types. This automatically handles positional parameters and
user-defined printf formats for ordinary parameter types; it doesn't
handle user-defined printf parameter types (such as defined by libdfp
for decimal floating-point).
Also add a (non-comprehensive) test.
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
Signed-off-by: Gergely Nagy <algernon@balabit.hu>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/umberlog.c | 97 | ||||
-rw-r--r-- | lib/umberlog.rst | 8 |
2 files changed, 98 insertions, 7 deletions
diff --git a/lib/umberlog.c b/lib/umberlog.c index b3fadbc..9266c76 100644 --- a/lib/umberlog.c +++ b/lib/umberlog.c @@ -28,6 +28,7 @@ #define _GNU_SOURCE 1 #define SYSLOG_NAMES 1 +#include "config.h" #include <stdarg.h> #include <sys/types.h> #include <unistd.h> @@ -42,8 +43,10 @@ #include <time.h> #include <errno.h> #include <wchar.h> +#ifdef HAVE_PARSE_PRINTF_FORMAT +#include <printf.h> +#endif -#include "config.h" #include "umberlog.h" #include "buffer.h" @@ -177,8 +180,88 @@ _get_hostname (void) return ul_sys_settings.hostname; } -static void -_ul_va_spin (const char *fmt, va_list *pap) +#ifdef HAVE_PARSE_PRINTF_FORMAT + +#define _ul_va_spin _ul_va_spin_glibc + +static int +_ul_va_spin_glibc (const char *fmt, va_list *pap) +{ + size_t num_args, i; + int *types; + + num_args = parse_printf_format (fmt, 0, NULL); + types = malloc (num_args * sizeof (*types)); + if (types == NULL) + goto err; + if (parse_printf_format (fmt, num_args, types) != num_args) + goto err; /* Should never happen */ + + for (i = 0; i < num_args; i++) + { + switch (types[i]) + { + case PA_CHAR: + case PA_INT | PA_FLAG_SHORT: + case PA_INT: + (void)va_arg (*pap, int); + break; + case PA_INT | PA_FLAG_LONG: + (void)va_arg (*pap, long int); + break; + case PA_INT | PA_FLAG_LONG_LONG: + (void)va_arg (*pap, long long int); + break; + + case PA_WCHAR: + (void)va_arg (*pap, wint_t); + break; + + case PA_STRING: + (void)va_arg (*pap, char *); + break; + + case PA_WSTRING: + (void)va_arg (*pap, wchar_t *); + break; + + case PA_POINTER: + (void)va_arg (*pap, void *); + break; + + case PA_FLOAT: + case PA_DOUBLE: + (void)va_arg (*pap, double); + break; + case PA_DOUBLE | PA_FLAG_LONG_DOUBLE: + (void)va_arg (*pap, long double); + break; + + default: + if ((types[i] & PA_FLAG_PTR) != 0) + { + (void)va_arg (*pap, void *); + break; + } + /* Unknown user-defined parameter type. Can we log that this + happened? */ + goto err; + } + } + + free (types); + return 0; + + err: + free (types); + return -1; +} +#else /* !HAVE_PARSE_PRINTF_FORMAT */ + +#define _ul_va_spin _ul_va_spin_legacy + +static int +_ul_va_spin_legacy (const char *fmt, va_list *pap) { size_t i; @@ -293,7 +376,9 @@ _ul_va_spin (const char *fmt, va_list *pap) } } } + return 0; } +#endif /* !HAVE_PARSE_PRINTF_FORMAT */ /* Return a newly allocated string. On failure, NULL is returned and it is undefined what PAP points to. */ @@ -314,7 +399,11 @@ _ul_vasprintf_and_advance (const char *fmt, va_list *pap) if (res == NULL) return NULL; - _ul_va_spin (fmt, pap); + if (_ul_va_spin (fmt, pap) != 0) + { + free (res); + return NULL; + } return res; } diff --git a/lib/umberlog.rst b/lib/umberlog.rst index 704a5e3..9883de4 100644 --- a/lib/umberlog.rst +++ b/lib/umberlog.rst @@ -7,7 +7,7 @@ CEE-enhanced syslog message generation -------------------------------------- :Author: Gergely Nagy <algernon@balabit.hu> -:Date: 2012-04-28 +:Date: 2012-07-19 :Manual section: 3 :Manual group: CEE-enhanced syslog Manual @@ -57,8 +57,10 @@ the emitted message. After the *msg_format* format string, and any other parameters it refers to, there must be a NULL-terminated list of *key*, *value format*, *format parameters*. Each of these pairs, constructed from the *key* and the **printf(3)**-style *value format* -will be added to the generated message. Note that position specifiers -(e.g. **%2$**) are not currently supported. +will be added to the generated message. + +Note that user-defined printf types defined by +**register_printf_type()** are not supported. **ul_format()** and **ul_vformat()** do the same as the syslog variants above, except the formatted payload is not sent to syslog, |