diff options
| author | Gergely Nagy <algernon@balabit.hu> | 2012-03-24 19:05:46 +0100 |
|---|---|---|
| committer | Gergely Nagy <algernon@balabit.hu> | 2012-03-24 19:05:46 +0100 |
| commit | bf66fd9161e9dbcbffe8215d72612f3805cf25e1 (patch) | |
| tree | 058d160fd9f8a91ce659038c1913f01686477f6a /lib | |
| parent | fcb18a0fdc2064a6ee39c58881a4ebc4a5661c68 (diff) | |
| parent | 9f6935065f4c844835774e8874fd38ad62363de0 (diff) | |
Merge branch 'master' into debian
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Makefile.am | 4 | ||||
| -rw-r--r-- | lib/umberlog.c | 209 | ||||
| -rw-r--r-- | lib/umberlog.h | 9 | ||||
| -rw-r--r-- | lib/umberlog.rst | 27 |
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 ======== |
