summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorGergely Nagy <algernon@balabit.hu>2012-07-19 13:34:49 +0200
committerGergely Nagy <algernon@balabit.hu>2012-07-19 13:34:49 +0200
commit841f531dd0e1a95a9ce08c78b85d388806229394 (patch)
tree66fca2c17e43c02bec5c5c99cfd2b96690d4d8b8 /lib
parentcd7703d466b98e9eb45df97b5d91794ef5bdeb90 (diff)
downloadlibumberlog-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.c97
-rw-r--r--lib/umberlog.rst8
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,