summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGergely Nagy <algernon@balabit.hu>2012-04-13 12:12:56 +0200
committerGergely Nagy <algernon@balabit.hu>2012-04-13 12:12:56 +0200
commit3c009dee6e7ac9ecff02596db924790c0683a049 (patch)
tree15379f28fdf5c857085f05a770b2862caab5bddf
parent63fcf21f9a9f616880dfb9c7174b8694423a7f75 (diff)
downloadlibumberlog-3c009dee6e7ac9ecff02596db924790c0683a049.tar.gz
libumberlog-3c009dee6e7ac9ecff02596db924790c0683a049.tar.xz
libumberlog-3c009dee6e7ac9ecff02596db924790c0683a049.zip
Format JSON ourselves, without json-c.
To make the library thinner, we now format JSON ourselves: there was so little we used from json-c, that doing it ourselves is lighter and faster. With this commit, we have the architecture in place, with only a few little things remaining to be done, such as escaping string values. Signed-off-by: Gergely Nagy <algernon@balabit.hu>
-rw-r--r--README.rst6
-rw-r--r--TODO.org6
-rw-r--r--lib/Makefile.am4
-rw-r--r--lib/buffer.c94
-rw-r--r--lib/buffer.h48
-rw-r--r--lib/umberlog.c130
6 files changed, 204 insertions, 84 deletions
diff --git a/README.rst b/README.rst
index 5d30d59..3147295 100644
--- a/README.rst
+++ b/README.rst
@@ -54,9 +54,9 @@ SSH Login::
Requirements
------------
-Apart from the autotools, a C compiler, and `json\-c`_, there are no
-other hard dependencies when building, except for a sufficiently
-modern system.
+Apart from the autotools, a C compiler, and `json\-c`_ (for the test
+suite), there are no other hard dependencies when building, except for
+a sufficiently modern system.
.. _json\-c: http://oss.metaparadigm.com/json-c/
diff --git a/TODO.org b/TODO.org
index fb4451b..7fa5221 100644
--- a/TODO.org
+++ b/TODO.org
@@ -97,7 +97,11 @@ systems where we would need to copy the thing around.
We need a way to get the post-message key-value pairs some other way,
or with using va_copy() and counting format strings and whatnot.
-* TODO Remove json-c dependency
+* WIP Remove json-c dependency
+- Note taken on [2012-04-13 Fri 12:09] \\
+ Work in progress: the buffer handling was moved to buffer.c, it does
+ the heavy lifting and JSON formatting. It does not do escaping yet,
+ however.
We use very little of json-c, all we do is append key-value pairs,
where both keys and values are always strings. We pretty much only use
json-c to escape these for us, if so need be.
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 5c64fb6..672ebf6 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -4,10 +4,8 @@ LUL_AGE = 0
lib_LTLIBRARIES = libumberlog.la
libumberlog_la_LDFLAGS = -Wl,--version-script,${srcdir}/libumberlog.ld
-libumberlog_la_LIBADD = @JSON_LIBS@
-libumberlog_la_CFLAGS = @JSON_CFLAGS@
-libumberlog_la_SOURCES = umberlog.c umberlog.h
+libumberlog_la_SOURCES = umberlog.c umberlog.h buffer.c buffer.h
libumberlog_includedir = $(includedir)
libumberlog_include_HEADERS = umberlog.h
diff --git a/lib/buffer.c b/lib/buffer.c
new file mode 100644
index 0000000..4f795eb
--- /dev/null
+++ b/lib/buffer.c
@@ -0,0 +1,94 @@
+/* buffer.c -- Auto-growing string buffers
+ *
+ * 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
+
+#include "config.h"
+#include "buffer.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+static inline ul_buffer_t *
+_ul_buffer_ensure_size (ul_buffer_t *buffer, size_t size)
+{
+ if (buffer->alloc < size)
+ {
+ buffer->alloc += size * 2;
+ buffer->msg = realloc (buffer->msg, buffer->alloc);
+ if (!buffer->msg)
+ return NULL;
+ }
+ return buffer;
+}
+
+ul_buffer_t *
+ul_buffer_reset (ul_buffer_t *buffer)
+{
+ buffer->len = 1;
+ _ul_buffer_ensure_size (buffer, 512);
+ buffer->msg[0] = '{';
+ return buffer;
+}
+
+ul_buffer_t *
+ul_buffer_append (ul_buffer_t *buffer, const char *key, const char *value)
+{
+ size_t lk, lv;
+
+ lk = strlen (key);
+ lv = strlen (value);
+
+ buffer = _ul_buffer_ensure_size (buffer, buffer->len + lk + lv + 6);
+ if (!buffer)
+ return NULL;
+
+ /* FIXME: Escpae stuff here */
+
+ memcpy (buffer->msg + buffer->len, "\"", 1);
+ memcpy (buffer->msg + buffer->len + 1, key, lk);
+ memcpy (buffer->msg + buffer->len + 1 + lk, "\":\"", 3);
+ memcpy (buffer->msg + buffer->len + 1 + lk + 3, value, lv);
+ memcpy (buffer->msg + buffer->len + 1 + lk + 3 + lv, "\",", 2);
+ buffer->len += lk + lv + 6;
+
+ return buffer;
+}
+
+char *
+ul_buffer_finalize (ul_buffer_t *buffer)
+{
+ if (buffer->msg[buffer->len] == ',')
+ buffer->msg[buffer->len] = '}';
+ else
+ {
+ if (!_ul_buffer_ensure_size (buffer, buffer->len + 1))
+ return NULL;
+ buffer->msg[buffer->len++] = '}';
+ }
+ return buffer->msg;
+}
diff --git a/lib/buffer.h b/lib/buffer.h
new file mode 100644
index 0000000..0d412e8
--- /dev/null
+++ b/lib/buffer.h
@@ -0,0 +1,48 @@
+/* buffer.h -- Auto-growing string buffers
+ *
+ * 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.
+ */
+
+#ifndef UMBERLOG_BUFFER_H
+#define UMBERLOG_BUFFER_H 1
+
+#include <stdlib.h>
+
+typedef struct
+{
+ size_t alloc;
+ size_t len;
+ char *msg;
+} ul_buffer_t;
+
+ul_buffer_t *ul_buffer_reset (ul_buffer_t *buffer)
+ __attribute__((visibility("hidden")));
+ul_buffer_t *ul_buffer_append (ul_buffer_t *buffer,
+ const char *key, const char *value)
+ __attribute__((visibility("hidden")));
+char *ul_buffer_finalize (ul_buffer_t *buffer)
+ __attribute__((visibility("hidden")));
+
+#endif
diff --git a/lib/umberlog.c b/lib/umberlog.c
index 78697c6..fe0a6b7 100644
--- a/lib/umberlog.c
+++ b/lib/umberlog.c
@@ -31,7 +31,6 @@
#include <stdarg.h>
#include <sys/types.h>
#include <unistd.h>
-#include <json.h>
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
@@ -44,6 +43,7 @@
#include "config.h"
#include "umberlog.h"
+#include "buffer.h"
static void (*old_syslog) ();
static void (*old_vsyslog) ();
@@ -65,6 +65,7 @@ static __thread struct
char hostname[_POSIX_HOST_NAME_MAX + 1];
} ul_sys_settings;
+static __thread ul_buffer_t ul_buffer;
static __thread int ul_recurse;
static void
@@ -231,8 +232,8 @@ _get_hostname (void)
} \
}
-static inline struct json_object *
-_ul_json_vappend (struct json_object *json, va_list ap)
+static inline ul_buffer_t *
+_ul_json_vappend (ul_buffer_t *buffer, va_list ap)
{
char *key;
@@ -240,7 +241,6 @@ _ul_json_vappend (struct json_object *json, va_list ap)
{
char *fmt = (char *)va_arg (ap, char *);
char *value = NULL;
- struct json_object *jstr;
va_list aq;
va_copy (aq, ap);
@@ -254,36 +254,36 @@ _ul_json_vappend (struct json_object *json, va_list ap)
if (!value)
return NULL;
- jstr = json_object_new_string (value);
- if (!jstr)
+ buffer = ul_buffer_append (buffer, key, value);
+
+ if (buffer == NULL)
{
free (value);
return NULL;
}
- json_object_object_add (json, key, jstr);
free (value);
_ul_va_spin (fmt, ap);
}
- return json;
+ return buffer;
}
-static inline struct json_object *
-_ul_json_append (struct json_object *json, ...)
+static inline ul_buffer_t *
+_ul_json_append (ul_buffer_t *buffer, ...)
{
va_list ap;
- va_start (ap, json);
- json = _ul_json_vappend (json, ap);
+ va_start (ap, buffer);
+ buffer = _ul_json_vappend (buffer, ap);
va_end (ap);
- return json;
+ return buffer;
}
-static inline struct json_object *
-_ul_json_append_timestamp (struct json_object *jo)
+static inline ul_buffer_t *
+_ul_json_append_timestamp (ul_buffer_t *buffer)
{
struct timespec ts;
struct tm *tm;
@@ -296,40 +296,39 @@ _ul_json_append_timestamp (struct json_object *jo)
strftime (stamp, sizeof (stamp), "%FT%T", tm);
strftime (zone, sizeof (zone), "%z", tm);
- return _ul_json_append (jo, "timestamp", "%s.%lu%s",
+ return _ul_json_append (buffer, "timestamp", "%s.%lu%s",
stamp, ts.tv_nsec, zone,
NULL);
}
-static inline struct json_object *
-_ul_discover (struct json_object *jo, int priority)
+static inline ul_buffer_t *
+_ul_discover (ul_buffer_t *buffer, int priority)
{
if (ul_sys_settings.flags & LOG_UL_NODISCOVER)
- 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);
+ return buffer;
+
+ buffer = _ul_json_append (buffer,
+ "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 || !buffer)
+ return buffer;
+
+ return _ul_json_append_timestamp (buffer);
}
-static inline struct json_object *
-_ul_vformat (struct json_object *jo, int format_version,
+static inline ul_buffer_t *
+_ul_vformat (ul_buffer_t *buffer, int format_version,
int priority, const char *msg_format,
va_list ap)
{
char *value;
- struct json_object *jstr;
va_list aq;
va_copy (aq, ap);
@@ -342,38 +341,37 @@ _ul_vformat (struct json_object *jo, int format_version,
if (!value)
return NULL;
- jstr = json_object_new_string (value);
- if (!jstr)
+ buffer = ul_buffer_append (buffer, "msg", value);
+ if (buffer == NULL)
{
free (value);
return NULL;
}
- json_object_object_add (jo, "msg", jstr);
free (value);
_ul_va_spin (msg_format, ap);
if (format_version > 0)
- jo = _ul_json_vappend (jo, ap);
+ buffer = _ul_json_vappend (buffer, ap);
- if (!jo)
+ if (!buffer)
return NULL;
- return _ul_discover (jo, priority);
+ return _ul_discover (buffer, priority);
}
static inline const char *
-_ul_vformat_str (struct json_object *jo, int format_version,
+_ul_vformat_str (ul_buffer_t *buffer, int format_version,
int priority, const char *msg_format,
va_list ap)
{
- jo = _ul_vformat (jo, format_version,
- priority, msg_format, ap);
- if (!jo)
+ buffer = _ul_vformat (buffer, format_version,
+ priority, msg_format, ap);
+ if (!buffer)
return NULL;
- return json_object_to_json_string (jo);
+ return ul_buffer_finalize (buffer);
}
/** Public API **/
@@ -393,26 +391,20 @@ ul_format (int priority, const char *msg_format, ...)
char *
ul_vformat (int priority, const char *msg_format, va_list ap)
{
- struct json_object *jo = json_object_new_object ();
char *result;
const char *msg;
+ ul_buffer_t *buffer = &ul_buffer;
- if (!jo)
- {
- errno = ENOMEM;
- return NULL;
- }
+ ul_buffer_reset (buffer);
- msg = _ul_vformat_str (jo, 1, priority, msg_format, ap);
+ msg = _ul_vformat_str (buffer, 1, priority, msg_format, ap);
if (!msg)
{
- json_object_put (jo);
errno = ENOMEM;
return NULL;
}
result = strdup (msg);
- json_object_put (jo);
return result;
}
@@ -420,33 +412,17 @@ static inline int
_ul_vsyslog (int format_version, int priority,
const char *msg_format, va_list ap)
{
- struct json_object *jo;
const char *msg;
+ ul_buffer_t *buffer = &ul_buffer;
if (!(ul_sys_settings.mask & priority))
return 0;
- jo = json_object_new_object ();
- if (!jo)
+ buffer = _ul_vformat (buffer, format_version, priority, msg_format, ap);
+ if (buffer == NULL)
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;
- }
-
- old_syslog (priority, "@cee:%s", msg);
-
- json_object_put (jo);
+ old_syslog (priority, "@cee:%s", ul_buffer_finalize (buffer));
return 0;
}