summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am4
-rw-r--r--lib/umberlog.c209
-rw-r--r--lib/umberlog.h9
-rw-r--r--lib/umberlog.rst27
4 files changed, 174 insertions, 75 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 030ae4e..5c64fb6 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -4,7 +4,7 @@ LUL_AGE = 0
lib_LTLIBRARIES = libumberlog.la
libumberlog_la_LDFLAGS = -Wl,--version-script,${srcdir}/libumberlog.ld
-libumberlog_la_LIBADD = @JSON_LIBS@ -ldl -lrt
+libumberlog_la_LIBADD = @JSON_LIBS@
libumberlog_la_CFLAGS = @JSON_CFLAGS@
libumberlog_la_SOURCES = umberlog.c umberlog.h
@@ -14,3 +14,5 @@ libumberlog_include_HEADERS = umberlog.h
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libumberlog.pc
+
+EXTRA_DIST = umberlog.rst libumberlog.ld
diff --git a/lib/umberlog.c b/lib/umberlog.c
index 151b333..ae9ebaf 100644
--- a/lib/umberlog.c
+++ b/lib/umberlog.c
@@ -39,13 +39,16 @@
#include <syslog.h>
#include <limits.h>
#include <time.h>
+#include <errno.h>
#include "umberlog.h"
#if __USE_FORTIFY_LEVEL > 0
static void (*old_syslog_chk) ();
+static void (*old_vsyslog_chk) ();
#else
static void (*old_syslog) ();
+static void (*old_vsyslog) ();
#endif
static void (*old_openlog) ();
@@ -63,16 +66,20 @@ static __thread struct
uid_t uid;
gid_t gid;
const char *ident;
- char hostname[HOST_NAME_MAX + 1];
+ char hostname[_POSIX_HOST_NAME_MAX + 1];
} ul_sys_settings;
+static __thread int ul_recurse;
+
static void
ul_init (void)
{
#if __USE_FORTIFY_LEVEL > 0
old_syslog_chk = dlsym (RTLD_NEXT, "__syslog_chk");
+ old_vsyslog_chk = dlsym (RTLD_NEXT, "__vsyslog_chk");
#else
old_syslog = dlsym (RTLD_NEXT, "syslog");
+ old_vsyslog = dlsym (RTLD_NEXT, "vsyslog");
#endif
old_openlog = dlsym (RTLD_NEXT, "openlog");
old_setlogmask = dlsym (RTLD_NEXT, "setlogmask");
@@ -90,11 +97,11 @@ ul_openlog (const char *ident, int option, int facility)
ul_sys_settings.uid = getuid ();
ul_sys_settings.ident = ident;
- gethostname (ul_sys_settings.hostname, HOST_NAME_MAX);
+ gethostname (ul_sys_settings.hostname, _POSIX_HOST_NAME_MAX);
}
/** HELPERS **/
-static const char *
+static inline const char *
_find_facility (void)
{
int i = 0;
@@ -108,7 +115,7 @@ _find_facility (void)
return "<unknown>";
}
-static const char *
+static inline const char *
_find_prio (int prio)
{
int i = 0;
@@ -155,11 +162,11 @@ static inline const char *
_get_hostname (void)
{
if (ul_sys_settings.flags & LOG_UL_NOCACHE)
- gethostname (ul_sys_settings.hostname, HOST_NAME_MAX);
+ gethostname (ul_sys_settings.hostname, _POSIX_HOST_NAME_MAX);
return ul_sys_settings.hostname;
}
-static struct json_object *
+static inline struct json_object *
_ul_json_vappend (struct json_object *json, va_list ap)
{
char *key;
@@ -167,29 +174,40 @@ _ul_json_vappend (struct json_object *json, va_list ap)
while ((key = (char *)va_arg (ap, char *)) != NULL)
{
char *fmt = (char *)va_arg (ap, char *);
- char *value;
+ char *value = NULL;
+ struct json_object *jstr;
if (vasprintf (&value, fmt, ap) == -1)
- abort ();
- json_object_object_add (json, key, json_object_new_string (value));
+ return NULL;
+ if (!value)
+ return NULL;
+
+ jstr = json_object_new_string (value);
+ if (!jstr)
+ {
+ free (value);
+ return NULL;
+ }
+
+ json_object_object_add (json, key, jstr);
free (value);
}
return json;
}
-static struct json_object *
+static inline struct json_object *
_ul_json_append (struct json_object *json, ...)
{
va_list ap;
va_start (ap, json);
- _ul_json_vappend (json, ap);
+ json = _ul_json_vappend (json, ap);
va_end (ap);
return json;
}
-static inline void
+static inline struct json_object *
_ul_json_append_timestamp (struct json_object *jo)
{
struct timespec ts;
@@ -203,51 +221,63 @@ _ul_json_append_timestamp (struct json_object *jo)
strftime (stamp, sizeof (stamp), "%FT%T", tm);
strftime (zone, sizeof (zone), "%z", tm);
- _ul_json_append (jo, "timestamp", "%s.%lu%s",
- stamp, ts.tv_nsec, zone,
- NULL);
+ return _ul_json_append (jo, "timestamp", "%s.%lu%s",
+ stamp, ts.tv_nsec, zone,
+ NULL);
}
-static inline void
+static inline struct json_object *
_ul_discover (struct json_object *jo, int priority)
{
if (ul_sys_settings.flags & LOG_UL_NODISCOVER)
- return;
-
- _ul_json_append (jo,
- "pid", "%d", _find_pid (),
- "facility", "%s", _find_facility (),
- "priority", "%s", _find_prio (priority),
- "program", "%s", ul_sys_settings.ident,
- "uid", "%d", _get_uid (),
- "gid", "%d", _get_gid (),
- "host", "%s", _get_hostname (),
- NULL);
-
- if (ul_sys_settings.flags & LOG_UL_NOTIME)
- return;
-
- _ul_json_append_timestamp (jo);
+ return jo;
+
+ jo = _ul_json_append (jo,
+ "pid", "%d", _find_pid (),
+ "facility", "%s", _find_facility (),
+ "priority", "%s", _find_prio (priority),
+ "program", "%s", ul_sys_settings.ident,
+ "uid", "%d", _get_uid (),
+ "gid", "%d", _get_gid (),
+ "host", "%s", _get_hostname (),
+ NULL);
+
+ if (ul_sys_settings.flags & LOG_UL_NOTIME || !jo)
+ return jo;
+
+ return _ul_json_append_timestamp (jo);
}
-static struct json_object *
+static inline struct json_object *
_ul_vformat (struct json_object *jo, int format_version,
int priority, const char *msg_format,
va_list ap)
{
char *value;
+ struct json_object *jstr;
if (vasprintf (&value, msg_format, ap) == -1)
- abort ();
- json_object_object_add (jo, "msg", json_object_new_string (value));
+ return NULL;
+ if (!value)
+ return NULL;
+
+ jstr = json_object_new_string (value);
+ if (!jstr)
+ {
+ free (value);
+ return NULL;
+ }
+
+ json_object_object_add (jo, "msg", jstr);
free (value);
if (format_version > 0)
- _ul_json_vappend (jo, ap);
+ jo = _ul_json_vappend (jo, ap);
- _ul_discover (jo, priority);
+ if (!jo)
+ return NULL;
- return jo;
+ return _ul_discover (jo, priority);
}
static inline const char *
@@ -255,9 +285,12 @@ _ul_vformat_str (struct json_object *jo, int format_version,
int priority, const char *msg_format,
va_list ap)
{
- return json_object_to_json_string (_ul_vformat (jo, format_version,
- priority, msg_format,
- ap));
+ jo = _ul_vformat (jo, format_version,
+ priority, msg_format, ap);
+ if (!jo)
+ return NULL;
+
+ return json_object_to_json_string (jo);
}
/** Public API **/
@@ -279,52 +312,102 @@ ul_vformat (int priority, const char *msg_format, va_list ap)
{
struct json_object *jo = json_object_new_object ();
char *result;
+ const char *msg;
- result = strdup (_ul_vformat_str (jo, 1, priority, msg_format, ap));
- json_object_put (jo);
- return result;
-}
+ if (!jo)
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
-void
-ul_syslog (int priority, const char *msg_format, ...)
-{
- va_list ap;
+ msg = _ul_vformat_str (jo, 1, priority, msg_format, ap);
+ if (!msg)
+ {
+ json_object_put (jo);
+ errno = ENOMEM;
+ return NULL;
+ }
- va_start (ap, msg_format);
- ul_vsyslog (priority, msg_format, ap);
- va_end (ap);
+ result = strdup (msg);
+ json_object_put (jo);
+ return result;
}
-static inline void
+static inline int
_ul_vsyslog (int format_version, int priority,
const char *msg_format, va_list ap)
{
struct json_object *jo;
+ const char *msg;
if (!(ul_sys_settings.mask & priority))
- return;
+ return 0;
+
+ jo = json_object_new_object ();
+ if (!jo)
+ return -1;
+
+ if (_ul_vformat (jo, format_version,
+ priority, msg_format, ap) == NULL)
+ {
+ json_object_put (jo);
+ return -1;
+ }
+
+ msg = json_object_to_json_string (jo);
+ if (!msg)
+ {
+ json_object_put (jo);
+ return -1;
+ }
- jo = _ul_vformat (json_object_new_object (), format_version,
- priority, msg_format, ap);
#if __USE_FORTIFY_LEVEL > 0
- old_syslog_chk (priority, __USE_FORTIFY_LEVEL - 1, "@cee:%s",
- json_object_to_json_string (jo));
+ old_syslog_chk (priority, __USE_FORTIFY_LEVEL - 1, "@cee:%s", msg);
#else
- old_syslog (priority, "@cee:%s", json_object_to_json_string (jo));
+ old_syslog (priority, "@cee:%s", msg);
#endif
+
json_object_put (jo);
+
+ return 0;
}
-void
+int
+ul_syslog (int priority, const char *msg_format, ...)
+{
+ va_list ap;
+ int status;
+
+ va_start (ap, msg_format);
+ status = ul_vsyslog (priority, msg_format, ap);
+ va_end (ap);
+
+ return status;
+}
+
+int
ul_vsyslog (int priority, const char *msg_format, va_list ap)
{
- _ul_vsyslog (1, priority, msg_format, ap);
+ return _ul_vsyslog (1, priority, msg_format, ap);
}
void
ul_legacy_vsyslog (int priority, const char *msg_format, va_list ap)
{
- _ul_vsyslog (0, priority, msg_format, ap);
+ if (ul_recurse)
+ {
+#if __USE_FORTIFY_LEVEL > 0
+ old_vsyslog_chk (priority, __USE_FORTIFY_LEVEL - 1, msg_format, ap);
+#else
+ old_vsyslog (priority, msg_format, ap);
+#endif
+ }
+ else
+ {
+ ul_recurse = 1;
+ _ul_vsyslog (0, priority, msg_format, ap);
+ }
+ ul_recurse = 0;
}
void
@@ -366,9 +449,11 @@ __vsyslog_chk (int __pri, int __flag, __const char *__fmt, va_list ap)
void openlog (const char *ident, int option, int facility)
__attribute__((alias ("ul_openlog")));
+#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.h b/lib/umberlog.h
index f91fe67..4245dae 100644
--- a/lib/umberlog.h
+++ b/lib/umberlog.h
@@ -36,14 +36,17 @@
#define LOG_UL_NOCACHE_UID 0x0100
#define LOG_UL_NOTIME 0x0200
-char *ul_format (int priority, const char *msg_format, ...);
+char *ul_format (int priority, const char *msg_format, ...)
+ __attribute__((sentinel));
char *ul_vformat (int priority, const char *msg_format, va_list ap);
void ul_openlog (const char *ident, int option, int facility);
int ul_setlogmask (int mask);
-void ul_syslog (int priority, const char *msg_format, ...);
-void ul_vsyslog (int priority, const char *msg_format, va_list ap);
+int ul_syslog (int priority, const char *msg_format, ...)
+ __attribute__((warn_unused_result, sentinel));
+int ul_vsyslog (int priority, const char *msg_format, va_list ap)
+ __attribute__((warn_unused_result));
void ul_legacy_syslog (int priority, const char *msg_format, ...);
void ul_legacy_vsyslog (int priority, const char *msg_format, va_list ap);
diff --git a/lib/umberlog.rst b/lib/umberlog.rst
index 036341b..26204e2 100644
--- a/lib/umberlog.rst
+++ b/lib/umberlog.rst
@@ -20,8 +20,8 @@ SYNOPSIS
void ul_openlog (const char *ident, int option, int facility);
- void ul_syslog (int priority, const char *format, ....);
- void ul_vsyslog (int priority, const char *format, va_list ap);
+ int ul_syslog (int priority, const char *format, ....);
+ int ul_vsyslog (int priority, const char *format, va_list ap);
void ul_legacy_syslog (int priority, const char *format, ...);
void ul_legacy_vsyslog (int priority, const char *format, va_list ap);
@@ -44,8 +44,8 @@ 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.
-_syslog()** and **ul_vsyslog()** are two new functions provided by the
-library, that have similar interface to the legacy **syslog()**
+**ul_syslog()** and **ul_vsyslog()** are two new functions provided by
+the library, that have similar interface to the legacy **syslog()**
functions, but they can be used to add arbitrary key-value pairs to
the emitted message. After the *msg_format* format string, and any
other parameters it refers to, there must be a NULL-terminated list of
@@ -57,6 +57,15 @@ will be added to the generated message.
variants above, except the formatted payload is not sent to syslog,
but returned as a newly allocated string.
+RETURN VALUE
+============
+
+When successful, **ul_syslog()** and **ul_vsyslog()** return zero,
+while **ul_format()** and **ul_vformat()** return a character string.
+
+On failure the former two will return non-zero, the latter two
+**NULL**, and set *errno* appropriately.
+
CEE PAYLOAD
===========
@@ -122,11 +131,11 @@ EXAMPLES
::
- ul_syslog(LOG_NOTICE, "Logged in user: %s", username,
- "service", "%s", service,
- "auth-method", "%s", auth_method,
- "sessionid", "%d", session_id,
- NULL);
+ status = ul_syslog(LOG_NOTICE, "Logged in user: %s", username,
+ "service", "%s", service,
+ "auth-method", "%s", auth_method,
+ "sessionid", "%d", session_id,
+ NULL);
SEE ALSO
========