summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGergely Nagy <algernon@balabit.hu>2012-08-10 14:07:29 +0200
committerGergely Nagy <algernon@balabit.hu>2012-08-10 16:53:06 +0200
commit8af1d67bd3e8a1766cb9984b3771162cc4c19669 (patch)
treed77ebb9f38a81c98a40bf41cbdc2548f987fd645
parent7d21f9316f32168acefcfe40b5b4b91c8378369c (diff)
downloadlibumberlog-8af1d67bd3e8a1766cb9984b3771162cc4c19669.tar.gz
libumberlog-8af1d67bd3e8a1766cb9984b3771162cc4c19669.tar.xz
libumberlog-8af1d67bd3e8a1766cb9984b3771162cc4c19669.zip
Split the library into a linkable and an LD_PRELOAD-able part
In order to satisfy the desire of using libumberlog, specifically ul_format(), without having to worry about syslog() & friends being overridden, split the library into two parts: A linkable library, which provides the new API, but does not override the legacy syslog() functions; and a new, LD_PRELOAD-able part, which does override the old ones. Signed-off-by: Gergely Nagy <algernon@balabit.hu>
-rw-r--r--README.rst19
-rw-r--r--lib/Makefile.am10
-rw-r--r--lib/umberlog.c32
-rw-r--r--lib/umberlog.rst27
-rw-r--r--lib/umberlog_preload.c64
-rw-r--r--t/Makefile.am17
-rw-r--r--t/test-common.c66
-rw-r--r--t/test-common.h14
-rw-r--r--t/test_umberlog.c343
-rw-r--r--t/test_umberlog_preload.c340
10 files changed, 555 insertions, 377 deletions
diff --git a/README.rst b/README.rst
index 8a23350..c6403c1 100644
--- a/README.rst
+++ b/README.rst
@@ -81,15 +81,16 @@ The library follows the usual autotools way of installation:
Usage
-----
-The library can either be used as an LD_PRELOAD-able shared object, in
-which case it overrides the system-supplied ``syslog()`` calls with
-its own, or as a proper library. In the latter case, please see the
-`API documentation`_ for more information.
-
-In the former case, using the library is as easy as setting
-**LD_PRELOAD** prior to executing a program (if one wants to control
-this on a per-program basis), or adding the path to the installed
-library to ``/etc/ld.so.preload``.
+The library comes in two variants: one to link against, and provides
+an enhanced, ``syslog()``-like API. For this, please see the `API
+documentation`_ for more information.
+
+The other variant is an LD_PRELOAD-able shared object, installed as
+``libumberlog_preload.so`` into a subdirectory of one's libdir. This
+one overrides the system-suploed ``syslog()`` calls with its own
+version, and turns these into CEE-emitting functions. It can be used
+either on a per-application basis, by setting **LD_PRELOAD**, or
+adding the path to the library to ``/etc/ld.so.preload``.
.. _API documentation: http://algernon.github.com/libumberlog/umberlog.html
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 100b633..4d0ee0c 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -16,8 +16,18 @@ libumberlog_include_HEADERS = umberlog.h
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libumberlog.pc
+pkglib_LTLIBRARIES = libumberlog_preload.la
+
+libumberlog_preload_la_SOURCES = umberlog_preload.c buffer.c buffer.h umberlog.h
+libumberlog_preload_la_LIBADD = -lpthread
+libumberlog_preload_la_LDFLAGS = -avoid-version -shared
+
EXTRA_DIST = umberlog.rst libumberlog.ld
+# We need this dependency, but can't compile umberlog.c into
+# libumberlog_preload.
+umberlog_preload.c: umberlog.c
+
if ENABLE_MANS
man3_MANS = umberlog.3
CLEANFILES = umberlog.3
diff --git a/lib/umberlog.c b/lib/umberlog.c
index f995ecd..3bb834a 100644
--- a/lib/umberlog.c
+++ b/lib/umberlog.c
@@ -710,35 +710,3 @@ ul_setlogmask (int mask)
{
return setlogmask (mask);
}
-
-#if HAVE___SYSLOG_CHK
-void
-__syslog_chk (int __pri, int __flag, __const char *__fmt, ...)
-{
- va_list ap;
-
- va_start (ap, __fmt);
- ul_legacy_vsyslog (__pri, __fmt, ap);
- va_end (ap);
-}
-
-void
-__vsyslog_chk (int __pri, int __flag, __const char *__fmt, va_list ap)
-{
- ul_legacy_vsyslog (__pri, __fmt, ap);
-}
-#endif
-
-void openlog (const char *ident, int option, int facility)
- __attribute__((alias ("ul_openlog")));
-
-void closelog (void)
- __attribute__((alias ("ul_closelog")));
-
-#undef syslog
-void syslog (int priority, const char *msg_format, ...)
- __attribute__((alias ("ul_legacy_syslog")));
-
-#undef vsyslog
-void vsyslog (int priority, const char *msg_format, va_list ap)
- __attribute__((alias ("ul_legacy_vsyslog")));
diff --git a/lib/umberlog.rst b/lib/umberlog.rst
index df71363..1c7b909 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-07-19
+:Date: 2012-08-10
:Manual section: 3
:Manual group: CEE-enhanced syslog Manual
@@ -33,20 +33,18 @@ SYNOPSIS
DESCRIPTION
===========
-**ul_openlog()** (also aliased to **openlog()**) is a wrapper around
-the original **openlog()** function, which opens a connection to the
-system logger for a program. The updated version adds support for a
-number of new option flags, described below.
+**ul_openlog()** is a wrapper around the original **openlog()**
+function, which opens a connection to the system logger for a
+program. The updated version adds support for a number of new option
+flags, described below.
-**ul_closelog()** (also aliased to **closelog()**) is similar to
-**ul_openlog()** in that it is a wrapper around the original
-**closelog()**.
+**ul_closelog()** is similar to **ul_openlog()** in that it is a
+wrapper around the original **closelog()**.
**ul_legacy_syslog()** and **ul_legacy_vsyslog()** are both thin
-layers over the original **syslog()** and **vsyslog()** functions, and
-the library overrides the original functions with this two. The only
-change these functions bring, are that the message they generate will
-be a CEE-enhanced message, with a JSON payload. See below for an
+layers over the original **syslog()** and **vsyslog()** functions. The
+only change these functions bring, are that the message they generate
+will be a CEE-enhanced message, with a JSON payload. See below for an
explanation on what this means.
**ul_syslog()** and **ul_vsyslog()** are two new functions provided by
@@ -65,6 +63,11 @@ Note that user-defined printf types defined by
variants above, except the formatted payload is not sent to syslog,
but returned as a newly allocated string.
+In the *LD_PRELOAD* variant of the library, **ul_openlog()** and
+**ul_closelog()** override the system-default **openlog()** and
+**closelog()** respectively, while **ul_legacy_syslog()** and
+**ul_legacy_vsyslog()** override **syslog()** and **vsyslog()**.
+
RETURN VALUE
============
diff --git a/lib/umberlog_preload.c b/lib/umberlog_preload.c
new file mode 100644
index 0000000..eb5a8d7
--- /dev/null
+++ b/lib/umberlog_preload.c
@@ -0,0 +1,64 @@
+/* umberlog_preload.c -- CEE-enhanced syslog API, LD_PRELOAD version
+ *
+ * Copyright (c) 2012 BalaBit IT Security Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BALABIT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BALABIT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define _GNU_SOURCE 1
+
+#define __UL_PRELOAD__ 1
+
+#include "umberlog.c"
+
+#if HAVE___SYSLOG_CHK
+void
+__syslog_chk (int __pri, int __flag, __const char *__fmt, ...)
+{
+ va_list ap;
+
+ va_start (ap, __fmt);
+ ul_legacy_vsyslog (__pri, __fmt, ap);
+ va_end (ap);
+}
+
+void
+__vsyslog_chk (int __pri, int __flag, __const char *__fmt, va_list ap)
+{
+ ul_legacy_vsyslog (__pri, __fmt, ap);
+}
+#endif
+
+void openlog (const char *ident, int option, int facility)
+ __attribute__((alias ("ul_openlog")));
+
+void closelog (void)
+ __attribute__((alias ("ul_closelog")));
+
+#undef syslog
+void syslog (int priority, const char *msg_format, ...)
+ __attribute__((alias ("ul_legacy_syslog")));
+
+#undef vsyslog
+void vsyslog (int priority, const char *msg_format, va_list ap)
+ __attribute__((alias ("ul_legacy_vsyslog")));
diff --git a/t/Makefile.am b/t/Makefile.am
index d6a0118..3f3a973 100644
--- a/t/Makefile.am
+++ b/t/Makefile.am
@@ -1,8 +1,15 @@
if ENABLE_TESTS
-TESTS = test_umberlog test_perf
-check_PROGRAMS = ${TESTS}
+TESTS = test_umberlog_preload test_umberlog test_perf
+check_PROGRAMS = ${TESTS}
-AM_CFLAGS = -I$(top_srcdir)/lib @JSON_CFLAGS@ @CHECK_CFLAGS@
-AM_LDFLAGS = -no-install
-LDADD = $(top_builddir)/lib/libumberlog.la @JSON_LIBS@ @CHECK_LIBS@
+AM_CFLAGS = -I$(top_srcdir)/lib @JSON_CFLAGS@ @CHECK_CFLAGS@
+AM_LDFLAGS = -no-install
+LDADD = @JSON_LIBS@ @CHECK_LIBS@
+
+check_LTLIBRARIES = libultest.la
+libultest_la_SOURCES = test-common.c test-common.h
+
+test_umberlog_preload_LDADD = ${LDADD} $(top_builddir)/lib/libumberlog_preload.la libultest.la
+test_umberlog_LDADD = ${LDADD} $(top_builddir)/lib/libumberlog.la libultest.la
+test_perf_LDADD = ${LDADD} $(top_builddir)/lib/libumberlog.la libultest.la
endif
diff --git a/t/test-common.c b/t/test-common.c
new file mode 100644
index 0000000..707a5c7
--- /dev/null
+++ b/t/test-common.c
@@ -0,0 +1,66 @@
+#define _GNU_SOURCE 1
+
+#include <json.h>
+#include <assert.h>
+#include <check.h>
+
+void
+verify_value (struct json_object *jo, const char *key,
+ const char *expected_value)
+{
+ struct json_object *o;
+ const char *value;
+
+ o = json_object_object_get (jo, key);
+
+ ck_assert (o != NULL);
+
+ value = json_object_get_string (o);
+
+ ck_assert_str_eq (value, expected_value);
+}
+
+void
+verify_value_differs (struct json_object *jo, const char *key,
+ const char *unexpected_value)
+{
+ struct json_object *o;
+ const char *value;
+
+ o = json_object_object_get (jo, key);
+
+ ck_assert (o != NULL);
+
+ value = json_object_get_string (o);
+
+ ck_assert_str_ne (value, unexpected_value);
+}
+
+void
+verify_value_exists (struct json_object *jo, const char *key)
+{
+ struct json_object *o;
+
+ o = json_object_object_get (jo, key);
+ ck_assert_msg (o != NULL, "key '%s' does not exist", key);
+}
+
+void
+verify_value_missing (struct json_object *jo, const char *key)
+{
+ struct json_object *o;
+
+ o = json_object_object_get (jo, key);
+ assert (o == NULL);
+}
+
+struct json_object *
+parse_msg (const char *msg)
+{
+ struct json_object *jo;
+
+ jo = json_tokener_parse (msg);
+ assert (jo != NULL);
+
+ return jo;
+}
diff --git a/t/test-common.h b/t/test-common.h
new file mode 100644
index 0000000..dcf6f64
--- /dev/null
+++ b/t/test-common.h
@@ -0,0 +1,14 @@
+#ifndef UMBERLOG_TEST_COMMON_H
+#define UMBERLOG_TEST_COMMON_H 1
+
+#include <json.h>
+
+void verify_value (struct json_object *jo, const char *key,
+ const char *expected_value);
+void verify_value_differs (struct json_object *jo, const char *key,
+ const char *unexpected_value);
+void verify_value_exists (struct json_object *jo, const char *key);
+void verify_value_missing (struct json_object *jo, const char *key);
+
+struct json_object *parse_msg (const char *msg);
+#endif
diff --git a/t/test_umberlog.c b/t/test_umberlog.c
index 88ea18f..21ac50d 100644
--- a/t/test_umberlog.c
+++ b/t/test_umberlog.c
@@ -2,6 +2,8 @@
#include "umberlog.h"
#include "config.h"
+#include "test-common.h"
+
#include <json.h>
#include <assert.h>
#include <string.h>
@@ -13,74 +15,14 @@
#include <check.h>
-static void
-verify_value (struct json_object *jo, const char *key,
- const char *expected_value)
-{
- struct json_object *o;
- const char *value;
-
- o = json_object_object_get (jo, key);
-
- ck_assert (o != NULL);
-
- value = json_object_get_string (o);
-
- ck_assert_str_eq (value, expected_value);
-}
-
-static void
-verify_value_differs (struct json_object *jo, const char *key,
- const char *unexpected_value)
-{
- struct json_object *o;
- const char *value;
-
- o = json_object_object_get (jo, key);
-
- ck_assert (o != NULL);
-
- value = json_object_get_string (o);
-
- ck_assert_str_ne (value, unexpected_value);
-}
-
-static void
-verify_value_exists (struct json_object *jo, const char *key)
-{
- struct json_object *o;
-
- o = json_object_object_get (jo, key);
- ck_assert_msg (o != NULL, "key '%s' does not exist", key);
-}
-
-static void
-verify_value_missing (struct json_object *jo, const char *key)
-{
- struct json_object *o;
-
- o = json_object_object_get (jo, key);
- assert (o == NULL);
-}
-static struct json_object *
-parse_msg (const char *msg)
-{
- struct json_object *jo;
-
- jo = json_tokener_parse (msg);
- assert (jo != NULL);
-
- return jo;
-}
-
-START_TEST (test_simple)
+START_TEST (test_overrides)
{
char *msg;
struct json_object *jo;
char host[_POSIX_HOST_NAME_MAX + 1];
- openlog ("umberlog/test_simple", 0, LOG_LOCAL0);
+ openlog ("umberlog/test_overrides", 0, LOG_LOCAL0);
msg = ul_format (LOG_DEBUG, "hello, I'm %s!", __FUNCTION__, NULL);
jo = parse_msg (msg);
@@ -88,10 +30,14 @@ START_TEST (test_simple)
gethostname (host, _POSIX_HOST_NAME_MAX);
- verify_value (jo, "msg", "hello, I'm test_simple!");
- verify_value (jo, "facility", "local0");
+ verify_value (jo, "msg", "hello, I'm test_overrides!");
+ /* Default facility is user, and since we did not catch openlog, it
+ should not change. */
+ verify_value (jo, "facility", "user");
verify_value (jo, "priority", "debug");
- verify_value (jo, "program", "umberlog/test_simple");
+ /* The program is also caught by openlog(), so we'll get the
+ default back, unless we use ul_openlog(). */
+ verify_value (jo, "program", "test_umberlog");
verify_value_exists (jo, "pid");
verify_value_exists (jo, "uid");
verify_value_exists (jo, "gid");
@@ -104,261 +50,33 @@ START_TEST (test_simple)
}
END_TEST
-START_TEST (test_no_discover)
+START_TEST (test_ul_openlog)
{
char *msg;
struct json_object *jo;
+ char host[_POSIX_HOST_NAME_MAX + 1];
- openlog ("umberlog/test_no_discover", LOG_UL_NODISCOVER, LOG_LOCAL0);
+ ul_openlog ("umberlog/test_ul_openlog", 0, LOG_LOCAL0);
msg = ul_format (LOG_DEBUG, "hello, I'm %s!", __FUNCTION__, NULL);
jo = parse_msg (msg);
free (msg);
- verify_value (jo, "msg", "hello, I'm test_no_discover!");
- verify_value_missing (jo, "facility");
- verify_value_missing (jo, "priority");
- verify_value_missing (jo, "program");
- verify_value_missing (jo, "pid");
- verify_value_missing (jo, "uid");
- verify_value_missing (jo, "gid");
- verify_value_missing (jo, "host");
- verify_value_missing (jo, "timestamp");
-
- json_object_put (jo);
-
- closelog ();
-}
-END_TEST
-
-START_TEST (test_additional_fields)
-{
- char *msg;
- struct json_object *jo;
-
- openlog ("umberlog/test_additional_fields", 0, LOG_LOCAL0);
-
- msg = ul_format (LOG_DEBUG, "testing 1, 2, 3...",
- "random_number", "%d", 42,
- "random_string", "fourty-two",
- NULL);
- jo = parse_msg (msg);
- free (msg);
-
- verify_value (jo, "msg", "testing 1, 2, 3...");
- verify_value (jo, "random_number", "42");
- verify_value (jo, "random_string", "fourty-two");
-
- json_object_put (jo);
-
- closelog ();
-}
-END_TEST
-
-START_TEST (test_discover_priority)
-{
- char *msg, *pid;
- struct json_object *jo;
-
- openlog ("umberlog/test_discover_priority", 0, LOG_LOCAL0);
-
- msg = ul_format (LOG_DEBUG, "testing 1, 2, 3...",
- "pid", "%d", getpid () + 42,
- NULL);
- jo = parse_msg (msg);
- free (msg);
-
- verify_value (jo, "msg", "testing 1, 2, 3...");
-
- if (asprintf (&pid, "%d", getpid ()) == -1)
- abort ();
- verify_value (jo, "pid", pid);
- free (pid);
-
- json_object_put (jo);
-
- closelog ();
-}
-END_TEST
-
-START_TEST (test_no_timestamp)
-{
- char *msg;
- struct json_object *jo;
-
- openlog ("umberlog/test_no_timestamp", LOG_UL_NOTIME, LOG_LOCAL0);
-
- msg = ul_format (LOG_DEBUG, "hello, I'm %s!", __FUNCTION__, NULL);
- jo = parse_msg (msg);
- free (msg);
+ gethostname (host, _POSIX_HOST_NAME_MAX);
- verify_value (jo, "msg", "hello, I'm test_no_timestamp!");
+ verify_value (jo, "msg", "hello, I'm test_ul_openlog!");
verify_value (jo, "facility", "local0");
verify_value (jo, "priority", "debug");
- verify_value (jo, "program", "umberlog/test_no_timestamp");
+ verify_value (jo, "program", "umberlog/test_ul_openlog");
verify_value_exists (jo, "pid");
verify_value_exists (jo, "uid");
verify_value_exists (jo, "gid");
- verify_value_missing (jo, "timestamp");
- verify_value_exists (jo, "host");
-
- json_object_put (jo);
-
- closelog ();
-}
-END_TEST
-
-START_TEST (test_json_escape)
-{
- static const char control_chars[] =
- "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
- "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
- "\x20";
-
- char *msg;
- struct json_object *jo;
-
- openlog ("umberlog/test_json_escape", LOG_UL_NODISCOVER, LOG_LOCAL0);
-
- msg = ul_format (LOG_DEBUG, "%s", __FUNCTION__,
- "quotes", "Hi, \"quoted value\" speaking!",
- "\"really\"", "yeah",
- "control", "foo\nbar",
- "utf8", "Árvíztűrő tükörfúrógép",
- "junk", "\013foo",
- "all_control", control_chars,
- NULL);
- jo = parse_msg (msg);
- free (msg);
-
- verify_value (jo, "quotes", "Hi, \"quoted value\" speaking!");
- verify_value (jo, "\"really\"", "yeah");
- verify_value (jo, "control", "foo\nbar");
- verify_value (jo, "utf8", "Árvíztűrő tükörfúrógép");
- verify_value (jo, "junk", "\013foo");
- verify_value (jo, "all_control", control_chars);
-
- json_object_put (jo);
-
- closelog ();
-}
-END_TEST
-
-START_TEST (test_facprio)
-{
- char *msg;
- struct json_object *jo;
-
- msg = ul_format (LOG_LOCAL1 | LOG_DEBUG, "%s", __FUNCTION__,
- NULL);
- jo = parse_msg (msg);
- free (msg);
-
- verify_value (jo, "facility", "local1");
- verify_value (jo, "priority", "debug");
-
- json_object_put (jo);
-}
-END_TEST
-
-START_TEST (test_closelog)
-{
- char *msg;
- struct json_object *jo;
-
- openlog ("umberlog/test_closelog", LOG_UL_NODISCOVER, LOG_LOCAL0);
- closelog ();
-
- msg = ul_format (LOG_DEBUG, "%s", __FUNCTION__, NULL);
- jo = parse_msg (msg);
- free (msg);
-
- verify_value_missing (jo, "facility");
-
- json_object_put (jo);
-
- openlog ("umberlog/test_closelog", 0, LOG_LOCAL0);
- closelog ();
-
- msg = ul_format (LOG_DEBUG, "%s", __FUNCTION__, NULL);
- jo = parse_msg (msg);
- free (msg);
-
- verify_value (jo, "facility", "local0");
-#ifdef HAVE_PROGRAM_INVOCATION_SHORT_NAME
- verify_value (jo, "program", "test_umberlog");
-#else
- verify_value_missing (jo, "program");
-#endif
- verify_value_differs (jo, "pid", "0");
- if (getuid () != 0)
- verify_value_differs (jo, "uid", "0");
- if (getgid () != 0)
- verify_value_differs (jo, "gid", "0");
- verify_value_differs (jo, "host", "");
-
- json_object_put (jo);
-}
-END_TEST
-
-#ifdef HAVE_PARSE_PRINTF_FORMAT
-START_TEST (test_positional_params)
-{
- char *msg;
- struct json_object *jo;
-
- openlog ("umberlog/test_positional_params", LOG_UL_NOTIME, LOG_LOCAL0);
-
-#define COMPLEX_FORMAT \
- "%3$*5$.*2$hhd , %1$Lf , %4$.3s , %4$s", 1.0L, 5, (char)100, "prefix", -8
-#define COMPLEX_RESULT "00100 , 1.000000 , pre , prefix"
- msg = ul_format (LOG_DEBUG, COMPLEX_FORMAT,
- "simple1", "value1",
- "complex", COMPLEX_FORMAT,
- "simple2", "value2",
- NULL);
- jo = parse_msg (msg);
- free (msg);
-
- verify_value (jo, "msg", COMPLEX_RESULT);
- verify_value (jo, "simple1", "value1");
- verify_value (jo, "complex", COMPLEX_RESULT);
- verify_value (jo, "simple2", "value2");
-
- json_object_put (jo);
-
- closelog ();
-}
-END_TEST
-#endif
-
-/* This must be the first test! */
-START_TEST (test_openlog_defaults)
-{
- char *msg;
- struct json_object *jo;
-
- /* No openlog */
-
- msg = ul_format (LOG_ALERT, "message", NULL);
- jo = parse_msg (msg);
- free (msg);
+ verify_value_exists (jo, "timestamp");
+ verify_value (jo, "host", host);
- verify_value (jo, "facility", "user");
-#ifdef HAVE_PROGRAM_INVOCATION_SHORT_NAME
- verify_value (jo, "program", "test_umberlog");
-#else
- verify_value_missing (jo, "program");
-#endif
- verify_value_differs (jo, "pid", "0");
- if (getuid () != 0)
- verify_value_differs (jo, "uid", "0");
- if (getgid () != 0)
- verify_value_differs (jo, "gid", "0");
- verify_value_differs (jo, "host", "");
json_object_put (jo);
- closelog ();
+ ul_closelog ();
}
END_TEST
@@ -367,29 +85,16 @@ main (void)
{
Suite *s;
SRunner *sr;
- TCase *ft, *bt;
+ TCase *ft;
int nfailed;
- s = suite_create ("Umberlog functional testsuite");
+ s = suite_create ("Umberlog (linkable) functional testsuite");
ft = tcase_create ("Basic tests");
- tcase_add_test (ft, test_openlog_defaults);
- tcase_add_test (ft, test_simple);
- tcase_add_test (ft, test_no_discover);
- tcase_add_test (ft, test_additional_fields);
- tcase_add_test (ft, test_discover_priority);
- tcase_add_test (ft, test_no_timestamp);
-#ifdef HAVE_PARSE_PRINTF_FORMAT
- tcase_add_test (ft, test_positional_params);
-#endif
+ tcase_add_test (ft, test_overrides);
+ tcase_add_test (ft, test_ul_openlog);
suite_add_tcase (s, ft);
- bt = tcase_create ("Bug tests");
- tcase_add_test (bt, test_json_escape);
- tcase_add_test (bt, test_facprio);
- tcase_add_test (bt, test_closelog);
- suite_add_tcase (s, bt);
-
sr = srunner_create (s);
srunner_run_all (sr, CK_ENV);
diff --git a/t/test_umberlog_preload.c b/t/test_umberlog_preload.c
new file mode 100644
index 0000000..e931210
--- /dev/null
+++ b/t/test_umberlog_preload.c
@@ -0,0 +1,340 @@
+#define _GNU_SOURCE 1
+
+#include "umberlog.h"
+#include "config.h"
+#include "test-common.h"
+#include <json.h>
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <limits.h>
+
+#include <check.h>
+
+START_TEST (test_simple)
+{
+ char *msg;
+ struct json_object *jo;
+ char host[_POSIX_HOST_NAME_MAX + 1];
+
+ openlog ("umberlog/test_simple", 0, LOG_LOCAL0);
+
+ msg = ul_format (LOG_DEBUG, "hello, I'm %s!", __FUNCTION__, NULL);
+ jo = parse_msg (msg);
+ free (msg);
+
+ gethostname (host, _POSIX_HOST_NAME_MAX);
+
+ verify_value (jo, "msg", "hello, I'm test_simple!");
+ verify_value (jo, "facility", "local0");
+ verify_value (jo, "priority", "debug");
+ verify_value (jo, "program", "umberlog/test_simple");
+ verify_value_exists (jo, "pid");
+ verify_value_exists (jo, "uid");
+ verify_value_exists (jo, "gid");
+ verify_value_exists (jo, "timestamp");
+ verify_value (jo, "host", host);
+
+ json_object_put (jo);
+
+ closelog ();
+}
+END_TEST
+
+START_TEST (test_no_discover)
+{
+ char *msg;
+ struct json_object *jo;
+
+ openlog ("umberlog/test_no_discover", LOG_UL_NODISCOVER, LOG_LOCAL0);
+
+ msg = ul_format (LOG_DEBUG, "hello, I'm %s!", __FUNCTION__, NULL);
+ jo = parse_msg (msg);
+ free (msg);
+
+ verify_value (jo, "msg", "hello, I'm test_no_discover!");
+ verify_value_missing (jo, "facility");
+ verify_value_missing (jo, "priority");
+ verify_value_missing (jo, "program");
+ verify_value_missing (jo, "pid");
+ verify_value_missing (jo, "uid");
+ verify_value_missing (jo, "gid");
+ verify_value_missing (jo, "host");
+ verify_value_missing (jo, "timestamp");
+
+ json_object_put (jo);
+
+ closelog ();
+}
+END_TEST
+
+START_TEST (test_additional_fields)
+{
+ char *msg;
+ struct json_object *jo;
+
+ openlog ("umberlog/test_additional_fields", 0, LOG_LOCAL0);
+
+ msg = ul_format (LOG_DEBUG, "testing 1, 2, 3...",
+ "random_number", "%d", 42,
+ "random_string", "fourty-two",
+ NULL);
+ jo = parse_msg (msg);
+ free (msg);
+
+ verify_value (jo, "msg", "testing 1, 2, 3...");
+ verify_value (jo, "random_number", "42");
+ verify_value (jo, "random_string", "fourty-two");
+
+ json_object_put (jo);
+
+ closelog ();
+}
+END_TEST
+
+START_TEST (test_discover_priority)
+{
+ char *msg, *pid;
+ struct json_object *jo;
+
+ openlog ("umberlog/test_discover_priority", 0, LOG_LOCAL0);
+
+ msg = ul_format (LOG_DEBUG, "testing 1, 2, 3...",
+ "pid", "%d", getpid () + 42,
+ NULL);
+ jo = parse_msg (msg);
+ free (msg);
+
+ verify_value (jo, "msg", "testing 1, 2, 3...");
+
+ if (asprintf (&pid, "%d", getpid ()) == -1)
+ abort ();
+ verify_value (jo, "pid", pid);
+ free (pid);
+
+ json_object_put (jo);
+
+ closelog ();
+}
+END_TEST
+
+START_TEST (test_no_timestamp)
+{
+ char *msg;
+ struct json_object *jo;
+
+ openlog ("umberlog/test_no_timestamp", LOG_UL_NOTIME, LOG_LOCAL0);
+
+ msg = ul_format (LOG_DEBUG, "hello, I'm %s!", __FUNCTION__, NULL);
+ jo = parse_msg (msg);
+ free (msg);
+
+ verify_value (jo, "msg", "hello, I'm test_no_timestamp!");
+ verify_value (jo, "facility", "local0");
+ verify_value (jo, "priority", "debug");
+ verify_value (jo, "program", "umberlog/test_no_timestamp");
+ verify_value_exists (jo, "pid");
+ verify_value_exists (jo, "uid");
+ verify_value_exists (jo, "gid");
+ verify_value_missing (jo, "timestamp");
+ verify_value_exists (jo, "host");
+
+ json_object_put (jo);
+
+ closelog ();
+}
+END_TEST
+
+START_TEST (test_json_escape)
+{
+ static const char control_chars[] =
+ "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+ "\x20";
+
+ char *msg;
+ struct json_object *jo;
+
+ openlog ("umberlog/test_json_escape", LOG_UL_NODISCOVER, LOG_LOCAL0);
+
+ msg = ul_format (LOG_DEBUG, "%s", __FUNCTION__,
+ "quotes", "Hi, \"quoted value\" speaking!",
+ "\"really\"", "yeah",
+ "control", "foo\nbar",
+ "utf8", "Árvíztűrő tükörfúrógép",
+ "junk", "\013foo",
+ "all_control", control_chars,
+ NULL);
+ jo = parse_msg (msg);
+ free (msg);
+
+ verify_value (jo, "quotes", "Hi, \"quoted value\" speaking!");
+ verify_value (jo, "\"really\"", "yeah");
+ verify_value (jo, "control", "foo\nbar");
+ verify_value (jo, "utf8", "Árvíztűrő tükörfúrógép");
+ verify_value (jo, "junk", "\013foo");
+ verify_value (jo, "all_control", control_chars);
+
+ json_object_put (jo);
+
+ closelog ();
+}
+END_TEST
+
+START_TEST (test_facprio)
+{
+ char *msg;
+ struct json_object *jo;
+
+ msg = ul_format (LOG_LOCAL1 | LOG_DEBUG, "%s", __FUNCTION__,
+ NULL);
+ jo = parse_msg (msg);
+ free (msg);
+
+ verify_value (jo, "facility", "local1");
+ verify_value (jo, "priority", "debug");
+
+ json_object_put (jo);
+}
+END_TEST
+
+START_TEST (test_closelog)
+{
+ char *msg;
+ struct json_object *jo;
+
+ openlog ("umberlog/test_closelog", LOG_UL_NODISCOVER, LOG_LOCAL0);
+ closelog ();
+
+ msg = ul_format (LOG_DEBUG, "%s", __FUNCTION__, NULL);
+ jo = parse_msg (msg);
+ free (msg);
+
+ verify_value_missing (jo, "facility");
+
+ json_object_put (jo);
+
+ openlog ("umberlog/test_closelog", 0, LOG_LOCAL0);
+ closelog ();
+
+ msg = ul_format (LOG_DEBUG, "%s", __FUNCTION__, NULL);
+ jo = parse_msg (msg);
+ free (msg);
+
+ verify_value (jo, "facility", "local0");
+#ifdef HAVE_PROGRAM_INVOCATION_SHORT_NAME
+ verify_value (jo, "program", "test_umberlog_preload");
+#else
+ verify_value_missing (jo, "program");
+#endif
+ verify_value_differs (jo, "pid", "0");
+ if (getuid () != 0)
+ verify_value_differs (jo, "uid", "0");
+ if (getgid () != 0)
+ verify_value_differs (jo, "gid", "0");
+ verify_value_differs (jo, "host", "");
+
+ json_object_put (jo);
+}
+END_TEST
+
+#ifdef HAVE_PARSE_PRINTF_FORMAT
+START_TEST (test_positional_params)
+{
+ char *msg;
+ struct json_object *jo;
+
+ openlog ("umberlog/test_positional_params", LOG_UL_NOTIME, LOG_LOCAL0);
+
+#define COMPLEX_FORMAT \
+ "%3$*5$.*2$hhd , %1$Lf , %4$.3s , %4$s", 1.0L, 5, (char)100, "prefix", -8
+#define COMPLEX_RESULT "00100 , 1.000000 , pre , prefix"
+ msg = ul_format (LOG_DEBUG, COMPLEX_FORMAT,
+ "simple1", "value1",
+ "complex", COMPLEX_FORMAT,
+ "simple2", "value2",
+ NULL);
+ jo = parse_msg (msg);
+ free (msg);
+
+ verify_value (jo, "msg", COMPLEX_RESULT);
+ verify_value (jo, "simple1", "value1");
+ verify_value (jo, "complex", COMPLEX_RESULT);
+ verify_value (jo, "simple2", "value2");
+
+ json_object_put (jo);
+
+ closelog ();
+}
+END_TEST
+#endif
+
+/* This must be the first test! */
+START_TEST (test_openlog_defaults)
+{
+ char *msg;
+ struct json_object *jo;
+
+ /* No openlog */
+
+ msg = ul_format (LOG_ALERT, "message", NULL);
+ jo = parse_msg (msg);
+ free (msg);
+
+ verify_value (jo, "facility", "user");
+#ifdef HAVE_PROGRAM_INVOCATION_SHORT_NAME
+ verify_value (jo, "program", "test_umberlog_preload");
+#else
+ verify_value_missing (jo, "program");
+#endif
+ verify_value_differs (jo, "pid", "0");
+ if (getuid () != 0)
+ verify_value_differs (jo, "uid", "0");
+ if (getgid () != 0)
+ verify_value_differs (jo, "gid", "0");
+ verify_value_differs (jo, "host", "");
+ json_object_put (jo);
+
+ closelog ();
+}
+END_TEST
+
+int
+main (void)
+{
+ Suite *s;
+ SRunner *sr;
+ TCase *ft, *bt;
+ int nfailed;
+
+ s = suite_create ("Umberlog (LD_PRELOAD) functional testsuite");
+
+ ft = tcase_create ("Basic tests");
+ tcase_add_test (ft, test_openlog_defaults);
+ tcase_add_test (ft, test_simple);
+ tcase_add_test (ft, test_no_discover);
+ tcase_add_test (ft, test_additional_fields);
+ tcase_add_test (ft, test_discover_priority);
+ tcase_add_test (ft, test_no_timestamp);
+#ifdef HAVE_PARSE_PRINTF_FORMAT
+ tcase_add_test (ft, test_positional_params);
+#endif
+ suite_add_tcase (s, ft);
+
+ bt = tcase_create ("Bug tests");
+ tcase_add_test (bt, test_json_escape);
+ tcase_add_test (bt, test_facprio);
+ tcase_add_test (bt, test_closelog);
+ suite_add_tcase (s, bt);
+
+ sr = srunner_create (s);
+
+ srunner_run_all (sr, CK_ENV);
+ nfailed = srunner_ntests_failed (sr);
+ srunner_free (sr);
+
+ return (nfailed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}