1 /*
2 * Copyright (c) 2015 Balabit
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 as published
6 * by the Free Software Foundation, or (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * As an additional exemption you are allowed to compile & link against the
18 * OpenSSL libraries as published by the OpenSSL project. See the file
19 * COPYING for details.
20 *
21 */
22
23 #include "format-welf.h"
24 #include "utf8utils.h"
25 #include "value-pairs/cmdline.h"
26
27 typedef struct _TFWelfState
28 {
29 TFSimpleFuncState super;
30 ValuePairs *vp;
31 } TFWelfState;
32
33 typedef struct _TFWelfIterState
34 {
35 GString *result;
36 gboolean initial_kv_pair_printed;
37 } TFWelfIterState;
38
39 static gboolean
tf_format_welf_prepare(LogTemplateFunction * self,gpointer s,LogTemplate * parent,gint argc,gchar * argv[],GError ** error)40 tf_format_welf_prepare(LogTemplateFunction *self, gpointer s, LogTemplate *parent,
41 gint argc, gchar *argv[],
42 GError **error)
43 {
44 TFWelfState *state = (TFWelfState *) s;
45
46 state->vp = value_pairs_new_from_cmdline (parent->cfg, &argc, &argv, FALSE, error);
47 if (!state->vp)
48 return FALSE;
49
50 return TRUE;
51 }
52
53 static gboolean
tf_format_welf_foreach(const gchar * name,TypeHint type,const gchar * value,gsize value_len,gpointer user_data)54 tf_format_welf_foreach(const gchar *name, TypeHint type, const gchar *value,
55 gsize value_len, gpointer user_data)
56 {
57 TFWelfIterState *iter_state = (TFWelfIterState *) user_data;
58 GString *result = iter_state->result;
59
60 if (iter_state->initial_kv_pair_printed)
61 g_string_append(result, " ");
62 else
63 iter_state->initial_kv_pair_printed = TRUE;
64
65 g_string_append(result, name);
66 g_string_append_c(result, '=');
67 if (memchr(value, ' ', value_len) == NULL)
68 append_unsafe_utf8_as_escaped_binary(result, value, value_len, NULL);
69 else
70 {
71 g_string_append_c(result, '"');
72 append_unsafe_utf8_as_escaped_binary(result, value, value_len, "\"");
73 g_string_append_c(result, '"');
74 }
75
76 return FALSE;
77 }
78
79 static gint
tf_format_welf_strcmp(gconstpointer a,gconstpointer b)80 tf_format_welf_strcmp(gconstpointer a, gconstpointer b)
81 {
82 gchar *sa = (gchar *)a, *sb = (gchar *)b;
83 if (strcmp (sa, "id") == 0)
84 return -1;
85 return strcmp(sa, sb);
86 }
87
88 static void
tf_format_welf_call(LogTemplateFunction * self,gpointer s,const LogTemplateInvokeArgs * args,GString * result)89 tf_format_welf_call(LogTemplateFunction *self, gpointer s, const LogTemplateInvokeArgs *args, GString *result)
90 {
91 TFWelfState *state = (TFWelfState *) s;
92 TFWelfIterState iter_state =
93 {
94 .result = result,
95 .initial_kv_pair_printed = FALSE
96 };
97 gint i;
98
99 for (i = 0; i < args->num_messages; i++)
100 {
101 value_pairs_foreach_sorted(state->vp,
102 tf_format_welf_foreach, (GCompareFunc) tf_format_welf_strcmp,
103 args->messages[i], args->options, &iter_state);
104 }
105
106 }
107
108 static void
tf_format_welf_free_state(gpointer s)109 tf_format_welf_free_state(gpointer s)
110 {
111 TFWelfState *state = (TFWelfState *) s;
112
113 value_pairs_unref(state->vp);
114 tf_simple_func_free_state(s);
115 }
116
117 TEMPLATE_FUNCTION(TFWelfState, tf_format_welf, tf_format_welf_prepare, NULL, tf_format_welf_call,
118 tf_format_welf_free_state, NULL);
119