[syslog-ng] [PATCH 1/3] value-pairs: A framework to filter key=value pairs.
Gergely Nagy
algernon at balabit.hu
Sun Apr 24 11:28:29 CEST 2011
This is the implementation of the value-pairs() framework discussed on
the list in the past.
The syntax is as follows:
destination d_driver {
driver(
value-pairs(
scope($SCOPE)
exclude("S_*") # shell-style glob to exclude keys
pair("my-own-key" "$SOURCE/$HOST")
key("HOST_FROM")
)
);
};
Of course, this is not only for destination drivers: there is support
for parsing arguments passed to template functions. The above set
would look like this in a template function:
$(function --scope $SCOPE --exclude S_* --pair my-own-key=$SOURCE/$HOST --key HOST_FROM)
The idea is that we select a scope (see later for the list of scopes
currently supported), from which we can exclude certain keys using a
shell-style glob pattern, or add custom key-value pairs of our own, or
add back pre-defined keys that we do want, but the scope doesn't have
by default.
The available scopes at the moment are:
* rfc3164: Key-value pairs based on the old syslog protocol, also
available as "core" and "base".
* rfc5424: Key-value pairs based on the new syslog protocol, also
available as "syslog_proto".
* all_macros: All macros known to syslog-ng (this only includes the
pre-defined macros!)
* selected_macros: A smaller set of selected macros, which the
developers deemed important (see the source for the list, for now).
* nv_pairs: Name-value pairs, the results of SDATA or patterndb
parsing.
* everything: All of the above, combined into one big set.
On the driver side, supporting value-pairs is reasonably easy:
driver_option
: value_pair_stmt {
driver_dd_set_value_pairs(last_driver, last_value_pairs);
}
| <etc...>
;
And in the driver itself, make a foreach callback:
static gboolean
driver_vp_foreach (const gchar *name, const gchar *value,
gpointer user_data)
{
/* Do something here with the name-value pairs */
return FALSE;
}
And whenever you want to work with the set, call
value_pairs_foreach():
value_pairs_foreach (self->value_pairs, driver_vp_foreach,
msg, self->seq_num, USER_DATA);
And that's about it.
Signed-off-by: Gergely Nagy <algernon at balabit.hu>
---
lib/Makefile.am | 3 +-
lib/cfg-grammar.y | 68 ++++++++-
lib/cfg-parser.c | 17 ++
lib/cfg-parser.h | 1 +
lib/syslog-ng.h | 2 +
lib/value-pairs.c | 458 +++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/value-pairs.h | 62 +++++++
7 files changed, 608 insertions(+), 3 deletions(-)
create mode 100644 lib/value-pairs.c
create mode 100644 lib/value-pairs.h
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 33a886e..16075b9 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -59,7 +59,8 @@ libsyslog_ng_la_SOURCES = \
block-ref-grammar.y block-ref-parser.c block-ref-parser.h \
pragma-grammar.y pragma-parser.h pragma-parser.c \
parser-expr-grammar.y parser-expr-parser.c parser-expr-parser.h \
- rewrite-expr-grammar.y rewrite-expr-parser.c rewrite-expr-parser.h
+ rewrite-expr-grammar.y rewrite-expr-parser.c rewrite-expr-parser.h \
+ value-pairs.c value-pairs.h
BUILT_SOURCES = cfg-lex.c cfg-lex.h cfg-grammar.c cfg-grammar.h \
filter-expr-grammar.y filter-expr-grammar.c filter-expr-grammar.h \
diff --git a/lib/cfg-grammar.y b/lib/cfg-grammar.y
index 0ec55ad..e1d97b6 100644
--- a/lib/cfg-grammar.y
+++ b/lib/cfg-grammar.y
@@ -28,6 +28,7 @@
#include "cfg-lexer.h"
#include "driver.h"
+#include "value-pairs.h"
}
%name-prefix "main_"
@@ -134,7 +135,6 @@
%token KW_SYSLOG 10060
-
/* option items */
%token KW_MARK_FREQ 10071
%token KW_STATS_FREQ 10072
@@ -263,6 +263,20 @@
%token LL_EOL 10428
%token LL_ERROR 10429
+/* value pairs */
+%token KW_VALUE_PAIRS 10500
+%token KW_SELECT 10501
+%token KW_EXCLUDE 10502
+%token KW_PAIR 10503
+%token KW_KEY 10504
+%token KW_SCOPE 10505
+%token KW_SCOPE_NV_PAIRS 10506
+%token KW_SCOPE_RFC3164 10507
+%token KW_SCOPE_RFC5424 10508
+%token KW_SCOPE_ALL_MACROS 10509
+%token KW_SCOPE_SELECTED_MACROS 10510
+%token KW_SCOPE_EVERYTHING 10511
+
/* END_DECLS */
%code {
@@ -277,6 +291,7 @@
#include "logreader.h"
#include "logparser.h"
#include "logrewrite.h"
+#include "value-pairs.h"
#include "filter-expr-parser.h"
#include "rewrite-expr-parser.h"
#include "block-ref-parser.h"
@@ -306,7 +321,7 @@ GList *last_rewrite_expr;
GList *last_parser_expr;
FilterExprNode *last_filter_expr;
CfgArgs *last_block_args;
-
+ValuePairs *last_value_pairs;
}
@@ -318,6 +333,7 @@ CfgArgs *last_block_args;
%type <ptr> log_stmt
%type <ptr> options_stmt
%type <ptr> template_stmt
+%type <ptr> value_pair_stmt
%type <ptr> source_items
%type <ptr> source_item
@@ -803,6 +819,54 @@ dest_writer_options_flags
| { $$ = 0; }
;
+value_pair_stmt
+ : KW_VALUE_PAIRS value_pairs_def { }
+ ;
+
+value_pairs_def
+ : { last_value_pairs = value_pairs_new(configuration); }
+ '(' value_pair_options ')'
+ { }
+ ;
+
+value_pair_options
+ : value_pair_option value_pair_options
+ |
+ ;
+
+value_pair_option
+ : KW_PAIR '(' string ':' string ')' { value_pairs_add_pair(last_value_pairs, $3, $5); free($3); free($5); }
+ | KW_PAIR '(' string string ')' { value_pairs_add_pair(last_value_pairs, $3, $4); free($3); free($4); }
+ | KW_KEY '(' string ')' {
+ gchar *k = g_strconcat("$", $3, NULL);
+ value_pairs_add_pair(last_value_pairs, $3, k);
+ g_free(k);
+ free($3);
+ }
+ | KW_EXCLUDE '(' string ')' { value_pairs_exclude_glob_pattern(last_value_pairs, $3); free($3); }
+ | KW_SCOPE '(' vp_scope_list ')' { }
+ ;
+
+vp_scope_list
+ : vp_scope vp_scope_list
+ |
+ ;
+
+vp_scope
+ : KW_SCOPE_NV_PAIRS
+ { value_pairs_add_scope(last_value_pairs, VALUE_PAIR_SCOPE_NV_PAIRS); }
+ | KW_SCOPE_RFC3164
+ { value_pairs_add_scope(last_value_pairs, VALUE_PAIR_SCOPE_RFC3164); }
+ | KW_SCOPE_RFC5424
+ { value_pairs_add_scope(last_value_pairs, VALUE_PAIR_SCOPE_RFC5424); }
+ | KW_SCOPE_ALL_MACROS
+ { value_pairs_add_scope(last_value_pairs, VALUE_PAIR_SCOPE_ALL_MACROS); }
+ | KW_SCOPE_SELECTED_MACROS
+ { value_pairs_add_scope(last_value_pairs, VALUE_PAIR_SCOPE_SELECTED_MACROS); }
+ | KW_SCOPE_EVERYTHING
+ { value_pairs_add_scope(last_value_pairs, VALUE_PAIR_SCOPE_EVERYTHING); }
+ ;
+
/* END_RULES */
diff --git a/lib/cfg-parser.c b/lib/cfg-parser.c
index e53c58d..1123d87 100644
--- a/lib/cfg-parser.c
+++ b/lib/cfg-parser.c
@@ -53,6 +53,23 @@ static CfgLexerKeyword main_keywords[] = {
{ "quote_pairs", KW_QUOTE_PAIRS, 0x0300},
{ "null", KW_NULL, 0x0300 },
+ /* value pairs */
+ { "value_pairs", KW_VALUE_PAIRS },
+ { "select", KW_SELECT },
+ { "exclude", KW_EXCLUDE },
+ { "pair", KW_PAIR },
+ { "key", KW_KEY },
+ { "scope", KW_SCOPE },
+ { "nv_pairs", KW_SCOPE_NV_PAIRS },
+ { "rfc3164", KW_SCOPE_RFC3164 },
+ { "core", KW_SCOPE_RFC3164 },
+ { "base", KW_SCOPE_RFC3164 },
+ { "rfc5424", KW_SCOPE_RFC5424 },
+ { "syslog_proto", KW_SCOPE_RFC5424 },
+ { "all_macros", KW_SCOPE_ALL_MACROS },
+ { "selected_macros", KW_SCOPE_SELECTED_MACROS },
+ { "everything", KW_SCOPE_EVERYTHING },
+
/* option items */
{ "flags", KW_FLAGS },
{ "pad_size", KW_PAD_SIZE },
diff --git a/lib/cfg-parser.h b/lib/cfg-parser.h
index 3527621..b874cd9 100644
--- a/lib/cfg-parser.h
+++ b/lib/cfg-parser.h
@@ -27,6 +27,7 @@
#include "syslog-ng.h"
#include "cfg-lexer.h"
+#include "value-pairs.h"
/* high level interface to a configuration file parser, it encapsulates the
* grammar/lexer pair. */
diff --git a/lib/syslog-ng.h b/lib/syslog-ng.h
index ce4c017..83a9651 100644
--- a/lib/syslog-ng.h
+++ b/lib/syslog-ng.h
@@ -61,10 +61,12 @@
typedef struct _LogMessage LogMessage;
typedef struct _GlobalConfig GlobalConfig;
+typedef struct _ValuePairs TValuePairs;
extern GlobalConfig *configuration;
extern gboolean seed_rng;
extern gchar *module_path;
extern gchar *default_modules;
+extern TValuePairs *last_value_pairs;
#endif
diff --git a/lib/value-pairs.c b/lib/value-pairs.c
new file mode 100644
index 0000000..5dfbb6f
--- /dev/null
+++ b/lib/value-pairs.c
@@ -0,0 +1,458 @@
+/*
+ * Copyright (c) 2002-2011 BalaBit IT Ltd, Budapest, Hungary
+ * Copyright (c) 2011 Gergely Nagy <algernon at balabit.hu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * As an additional exemption you are allowed to compile & link against the
+ * OpenSSL libraries as published by the OpenSSL project. See the file
+ * COPYING for details.
+ *
+ */
+
+#include "logmsg.h"
+#include "templates.h"
+
+#include "value-pairs.h"
+
+#include <string.h>
+
+typedef struct
+{
+ gchar *name;
+ LogTemplate *template;
+} vp_template_set;
+
+struct _ValuePairs
+{
+ GlobalConfig *cfg;
+
+ guint8 scopes;
+
+ GPatternSpec **excludes;
+ gsize exclude_size;
+ GHashTable *vpairs;
+
+ struct
+ {
+ vp_template_set *rfc3164;
+ vp_template_set *rfc5424;
+ vp_template_set *selected_macros;
+ vp_template_set *all_macros;
+ } templates;
+
+ /* Temporary */
+ GString *res;
+};
+
+static inline void
+vp_add_scope_template (GlobalConfig *cfg, vp_template_set *target,
+ gint index, const gchar *name, const gchar *macro)
+{
+ LogTemplate *t = NULL;
+ gchar *m;
+
+ if (macro)
+ m = g_strdup (macro);
+ else
+ m = g_strconcat ("$", name, NULL);
+
+ t = log_template_new(cfg, NULL, m);
+ target[index].name = g_strdup(name);
+ target[index].template = t;
+ g_free (m);
+}
+
+ValuePairs *
+value_pairs_new (GlobalConfig *cfg)
+{
+ ValuePairs *vp;
+ gint i = 0;
+
+ vp = g_try_new0(ValuePairs, 1);
+ if (!vp)
+ return NULL;
+ vp->res = g_string_sized_new(256);
+ if (!vp->res)
+ {
+ g_free(vp);
+ return NULL;
+ }
+ vp->vpairs = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+ (GDestroyNotify) log_template_unref);
+ if (!vp->vpairs)
+ {
+ g_string_free(vp->res, TRUE);
+ g_free(vp);
+ return NULL;
+ }
+
+ vp->cfg = cfg;
+
+ vp->templates.rfc3164 = g_try_new0 (vp_template_set, 8);
+ vp->templates.rfc5424 = g_try_new0 (vp_template_set, 3);
+ vp->templates.selected_macros = g_try_new0 (vp_template_set, 5);
+
+ while (macros[i].name)
+ i++;
+
+ vp->templates.all_macros = g_try_new0 (vp_template_set, i + 1);
+ i = 0;
+
+ vp_add_scope_template (vp->cfg, vp->templates.rfc3164, 0, "FACILITY", NULL);
+ vp_add_scope_template (vp->cfg, vp->templates.rfc3164, 1, "PRIORITY", NULL);
+ vp_add_scope_template (vp->cfg, vp->templates.rfc3164, 2, "DATE", "$S_DATE");
+ vp_add_scope_template (vp->cfg, vp->templates.rfc3164, 3, "HOST", NULL);
+ vp_add_scope_template (vp->cfg, vp->templates.rfc3164, 4, "PROGRAM", NULL);
+ vp_add_scope_template (vp->cfg, vp->templates.rfc3164, 5, "PID", NULL);
+ vp_add_scope_template (vp->cfg, vp->templates.rfc3164, 6, "MSG", NULL);
+
+ vp_add_scope_template (vp->cfg, vp->templates.rfc5424, 0, "MSGID", NULL);
+ vp_add_scope_template (vp->cfg, vp->templates.rfc5424, 1, "SDATA", NULL);
+
+ vp_add_scope_template (vp->cfg, vp->templates.selected_macros, 0, "TAGS", NULL);
+ vp_add_scope_template (vp->cfg, vp->templates.selected_macros, 1, "SDATA", NULL);
+ vp_add_scope_template (vp->cfg, vp->templates.selected_macros, 2, "SOURCEIP", NULL);
+ vp_add_scope_template (vp->cfg, vp->templates.selected_macros, 3, "SEQNUM", NULL);
+
+ while (macros[i].name)
+ {
+ vp_add_scope_template (vp->cfg, vp->templates.all_macros, i, macros[i].name, NULL);
+ i++;
+ }
+
+ return vp;
+}
+
+static gboolean
+vp_cmdline_parse_scope (const gchar *option_name, const gchar *value,
+ gpointer data, GError **error)
+{
+ ValuePairs *vp = (ValuePairs *)data;
+
+ if (g_ascii_strcasecmp (value, "nv_pairs") == 0)
+ value_pairs_add_scope (vp, VALUE_PAIR_SCOPE_NV_PAIRS);
+ else if (g_ascii_strcasecmp (value, "rfc3164") == 0 ||
+ g_ascii_strcasecmp (value, "core") == 0 ||
+ g_ascii_strcasecmp (value, "base"))
+ value_pairs_add_scope (vp, VALUE_PAIR_SCOPE_RFC3164);
+ else if (g_ascii_strcasecmp (value, "rfc5424") == 0 ||
+ g_ascii_strcasecmp (value, "syslog_proto") == 0)
+ value_pairs_add_scope (vp, VALUE_PAIR_SCOPE_RFC5424);
+ else if (g_ascii_strcasecmp (value, "selected_macros") == 0)
+ value_pairs_add_scope (vp, VALUE_PAIR_SCOPE_SELECTED_MACROS);
+ else if (g_ascii_strcasecmp (value, "all_macros") == 0)
+ value_pairs_add_scope (vp, VALUE_PAIR_SCOPE_ALL_MACROS);
+ else if (g_ascii_strcasecmp (value, "everything") == 0)
+ value_pairs_add_scope (vp, VALUE_PAIR_SCOPE_EVERYTHING);
+ else
+ {
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ "Error parsing value-pairs' scope()");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+vp_cmdline_parse_exclude (const gchar *option_name, const gchar *value,
+ gpointer data, GError **error)
+{
+ ValuePairs *vp = (ValuePairs *)data;
+
+ value_pairs_exclude_glob_pattern (vp, value);
+ return TRUE;
+}
+
+static gboolean
+vp_cmdline_parse_key (const gchar *option_name, const gchar *value,
+ gpointer data, GError **error)
+{
+ ValuePairs *vp = (ValuePairs *)data;
+ gchar *k = g_strconcat ("$", value, NULL);
+
+ value_pairs_add_pair (vp, value, k);
+ g_free (k);
+
+ return TRUE;
+}
+
+static gboolean
+vp_cmdline_parse_pair (const gchar *option_name, const gchar *value,
+ gpointer data, GError **error)
+{
+ ValuePairs *vp = (ValuePairs *)data;
+ gchar **kv;
+
+ if (!g_strstr_len (value, strlen (value), "="))
+ {
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ "Error parsing value-pairs' key=value pair");
+ return FALSE;
+ }
+
+ kv = g_strsplit(value, "=", 2);
+ value_pairs_add_pair (vp, kv[0], kv[1]);
+
+ g_free (kv[0]);
+ g_free (kv[1]);
+ g_free (kv);
+
+ return TRUE;
+}
+
+ValuePairs *
+value_pairs_new_from_cmdline (GlobalConfig *cfg,
+ gint cargc, gchar **cargv,
+ GError **error)
+{
+ ValuePairs *vp;
+ GOptionContext *ctx;
+ GOptionEntry vp_options[] = {
+ { "scope", 's', 0, G_OPTION_ARG_CALLBACK, vp_cmdline_parse_scope,
+ NULL, NULL },
+ { "exclude", 'x', 0, G_OPTION_ARG_CALLBACK, vp_cmdline_parse_exclude,
+ NULL, NULL },
+ { "key", 'k', 0, G_OPTION_ARG_CALLBACK, vp_cmdline_parse_key,
+ NULL, NULL },
+ { "pair", 'p', 0, G_OPTION_ARG_CALLBACK, vp_cmdline_parse_pair,
+ NULL, NULL },
+ { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_CALLBACK, vp_cmdline_parse_pair,
+ NULL, NULL },
+ { NULL }
+ };
+ gchar **argv;
+ gint argc = cargc + 1;
+ gint i;
+ GOptionGroup *og;
+
+ argv = g_new (gchar *, argc + 1);
+ for (i = 0; i < argc; i++)
+ argv[i + 1] = cargv[i];
+ argv[0] = "value-pairs";
+ argv[argc] = NULL;
+
+ vp = value_pairs_new (cfg);
+
+ ctx = g_option_context_new ("value-pairs");
+ og = g_option_group_new (NULL, NULL, NULL, vp, NULL);
+ g_option_group_add_entries (og, vp_options);
+ g_option_context_set_main_group (ctx, og);
+
+ if (!g_option_context_parse (ctx, &argc, &argv, error))
+ {
+ value_pairs_free (vp);
+ g_option_context_free (ctx);
+ g_free (argv);
+ return NULL;
+ }
+ g_option_context_free (ctx);
+
+ if (vp->scopes == 0)
+ value_pairs_add_scope (vp, VALUE_PAIR_SCOPE_RFC3164);
+
+ return vp;
+}
+
+void
+value_pairs_free (ValuePairs *vp)
+{
+ gint i;
+
+ if (!vp)
+ return;
+
+ g_hash_table_destroy(vp->vpairs);
+
+ for (i = 0; vp->templates.rfc3164[i].name; i++)
+ {
+ g_free (vp->templates.rfc3164[i].name);
+ log_template_unref (vp->templates.rfc3164[i].template);
+ }
+ g_free (vp->templates.rfc3164);
+
+ for (i = 0; vp->templates.rfc5424[i].name; i++)
+ {
+ g_free (vp->templates.rfc5424[i].name);
+ log_template_unref (vp->templates.rfc5424[i].template);
+ }
+ g_free (vp->templates.rfc5424);
+
+ for (i = 0; vp->templates.selected_macros[i].name; i++)
+ {
+ g_free (vp->templates.selected_macros[i].name);
+ log_template_unref (vp->templates.selected_macros[i].template);
+ }
+ g_free (vp->templates.selected_macros);
+
+ for (i = 0; vp->templates.all_macros[i].name; i++)
+ {
+ g_free (vp->templates.all_macros[i].name);
+ log_template_unref (vp->templates.all_macros[i].template);
+ }
+ g_free (vp->templates.all_macros);
+
+ for (i = 0; i < vp->exclude_size; i++)
+ g_pattern_spec_free(vp->excludes[i]);
+ g_free(vp->excludes);
+ g_string_free(vp->res, TRUE);
+ g_free(vp);
+}
+
+void
+value_pairs_add_scope (ValuePairs *vp, value_pair_scope_t scope)
+{
+ if (!vp)
+ return;
+
+ vp->scopes |= scope;
+}
+
+void
+value_pairs_exclude_glob_pattern (ValuePairs *vp, const gchar *pattern)
+{
+ gint i;
+
+ if (!vp || !pattern)
+ return;
+
+ i = vp->exclude_size++;
+ vp->excludes = g_renew(GPatternSpec *, vp->excludes, vp->exclude_size);
+ vp->excludes[i] = g_pattern_spec_new(pattern);
+}
+
+void
+value_pairs_add_pair (ValuePairs *vp, const gchar *key,
+ const gchar *value)
+{
+ LogTemplate *t = NULL;
+
+ if (!vp || !key || !value)
+ return;
+
+ t = log_template_new(vp->cfg, NULL, value);
+ g_hash_table_insert(vp->vpairs, g_strdup(key), t);
+}
+
+static void
+vp_foreach_merge_vp(gpointer key, gpointer value, gpointer user_data)
+{
+ ValuePairs *vp = ((gpointer *)user_data)[0];
+ LogMessage *msg = ((gpointer *)user_data)[2];
+ gint32 seq_num = GPOINTER_TO_INT (((gpointer *)user_data)[3]);
+ GHashTable *scope_set = ((gpointer *)user_data)[5];
+
+ g_string_truncate(vp->res, 0);
+ log_template_format((LogTemplate *)value, msg, NULL, LTZ_LOCAL,
+ seq_num, NULL, vp->res);
+
+ if (!vp->res->str || !vp->res->str[0])
+ return;
+
+ g_hash_table_insert(scope_set, key, g_strdup (vp->res->str));
+}
+
+static gboolean
+vp_foreach_nv_add(NVHandle handle, gchar *name,
+ const gchar *value, gssize value_len,
+ gpointer user_data)
+{
+ ValuePairs *vp = ((gpointer *)user_data)[0];
+ GHashTable *scope_set = ((gpointer *)user_data)[5];
+ gint j;
+
+ for (j = 0; j < vp->exclude_size; j++)
+ if (g_pattern_match_string(vp->excludes[j], name))
+ return FALSE;
+
+ g_hash_table_insert (scope_set, name, (gpointer)g_strndup (value, value_len));
+ return FALSE;
+}
+
+static void
+vp_foreach_merge_template (ValuePairs *vp, LogMessage *msg, gint32 seq_num,
+ vp_template_set *set, GHashTable *dest)
+{
+ gint i;
+
+ for (i = 0; set[i].name; i++)
+ {
+ gint j;
+ gboolean exclude = FALSE;
+
+ for (j = 0; j < vp->exclude_size; j++)
+ if (g_pattern_match_string(vp->excludes[j], set[i].name))
+ exclude = TRUE;
+ if (exclude)
+ continue;
+
+ g_string_truncate(vp->res, 0);
+ log_template_format(set[i].template, msg, NULL, LTZ_LOCAL, seq_num, NULL,
+ vp->res);
+
+ if (!vp->res->str || !vp->res->str[0])
+ continue;
+
+ g_hash_table_insert (dest, set[i].name, g_strdup (vp->res->str));
+ }
+}
+
+void
+value_pairs_foreach (ValuePairs *vp, VPForeachFunc func,
+ LogMessage *msg, gint32 seq_num, gpointer user_data)
+{
+ gpointer args[] = { vp, func, msg, GINT_TO_POINTER (seq_num), user_data, NULL };
+ GHashTable *scope_set;
+
+ scope_set = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
+ (GDestroyNotify) g_free);
+
+ args[5] = scope_set;
+
+ /*
+ * Build up the base set
+ */
+ if (vp->scopes & VALUE_PAIR_SCOPE_NV_PAIRS)
+ {
+ nv_table_foreach(msg->payload, logmsg_registry,
+ (NVTableForeachFunc)vp_foreach_nv_add, args);
+ }
+
+ if (vp->scopes & VALUE_PAIR_SCOPE_RFC3164 ||
+ vp->scopes & VALUE_PAIR_SCOPE_RFC5424 ||
+ vp->scopes & VALUE_PAIR_SCOPE_SELECTED_MACROS)
+ vp_foreach_merge_template (vp, msg, seq_num, vp->templates.rfc3164,
+ scope_set);
+
+ if (vp->scopes & VALUE_PAIR_SCOPE_RFC5424)
+ vp_foreach_merge_template (vp, msg, seq_num, vp->templates.rfc5424,
+ scope_set);
+
+ if (vp->scopes & VALUE_PAIR_SCOPE_SELECTED_MACROS)
+ vp_foreach_merge_template (vp, msg, seq_num, vp->templates.selected_macros,
+ scope_set);
+
+ if (vp->scopes & VALUE_PAIR_SCOPE_ALL_MACROS)
+ vp_foreach_merge_template (vp, msg, seq_num, vp->templates.all_macros,
+ scope_set);
+
+ /* Merge the explicit key-value pairs too */
+ g_hash_table_foreach (vp->vpairs, (GHFunc)vp_foreach_merge_vp, args);
+
+ /* Aaand we run it through the callback! */
+ g_hash_table_foreach (scope_set, (GHFunc)func, user_data);
+
+ g_hash_table_destroy (scope_set);
+}
diff --git a/lib/value-pairs.h b/lib/value-pairs.h
new file mode 100644
index 0000000..5642f28
--- /dev/null
+++ b/lib/value-pairs.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2002-2011 BalaBit IT Ltd, Budapest, Hungary
+ * Copyright (c) 2011 Gergely Nagy <algernon at balabit.hu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * As an additional exemption you are allowed to compile & link against the
+ * OpenSSL libraries as published by the OpenSSL project. See the file
+ * COPYING for details.
+ *
+ */
+
+#ifndef VALUE_PAIRS_H_INCLUDED
+#define VALUE_PAIRS_H_INCLUDED 1
+
+#include "syslog-ng.h"
+#include "nvtable.h"
+
+#include <glib.h>
+
+typedef enum
+ {
+ VALUE_PAIR_SCOPE_NV_PAIRS = 0x01,
+ VALUE_PAIR_SCOPE_RFC3164 = 0x02,
+ VALUE_PAIR_SCOPE_RFC5424 = 0x04,
+ VALUE_PAIR_SCOPE_ALL_MACROS = 0x08,
+ VALUE_PAIR_SCOPE_SELECTED_MACROS = 0x10,
+ VALUE_PAIR_SCOPE_EVERYTHING = 0xff,
+ } value_pair_scope_t;
+
+typedef struct _ValuePairs ValuePairs;
+typedef gboolean (*VPForeachFunc) (const gchar *name, const gchar *value,
+ gpointer user_data);
+
+ValuePairs *value_pairs_new (GlobalConfig *cfg);
+void value_pairs_free (ValuePairs *vp);
+
+void value_pairs_add_scope (ValuePairs *vp, value_pair_scope_t scope);
+void value_pairs_exclude_glob_pattern (ValuePairs *vp, const gchar *pattern);
+void value_pairs_add_pair (ValuePairs *vp, const gchar *key, const gchar *value);
+
+void value_pairs_foreach (ValuePairs *vp, VPForeachFunc func,
+ LogMessage *msg, gint32 seq_num,
+ gpointer user_data);
+
+ValuePairs *value_pairs_new_from_cmdline (GlobalConfig *cfg,
+ gint argc, gchar **argv,
+ GError **error);
+
+#endif
--
1.7.2.5
More information about the syslog-ng
mailing list