[syslog-ng] [PATCH] basicfuncs: Implement a few numeric template functions.

Gergely Nagy algernon at balabit.hu
Tue May 3 22:19:40 CEST 2011


Implement addition, substraction, multiplication, division and modulus
template functions: $(+ N M), $(- N M), $(* N M), $(/ N M) and $(% N
M), respectively.

All of them take two numeric arguments, and log an error, if they
receive less or more, or in case the number cannot be fully parsed as
a number.

Signed-off-by: Gergely Nagy <algernon at balabit.hu>
---
 modules/basicfuncs/basic-funcs.c |  120 +++++++++++++++++++++++++++++++++++++-
 tests/unit/test_template.c       |    9 +++
 2 files changed, 126 insertions(+), 3 deletions(-)

diff --git a/modules/basicfuncs/basic-funcs.c b/modules/basicfuncs/basic-funcs.c
index a03e221..2cc1442 100644
--- a/modules/basicfuncs/basic-funcs.c
+++ b/modules/basicfuncs/basic-funcs.c
@@ -23,7 +23,7 @@ tf_echo(LogMessage *msg, gint argc, GString *argv[], GString *result)
 TEMPLATE_FUNCTION_SIMPLE(tf_echo);
 
 static gboolean
-tf_substr_parse_int(const gchar *s, long *d)
+tf_parse_int(const gchar *s, long *d)
 {
   gchar *endptr;
   glong val;
@@ -42,6 +42,115 @@ tf_substr_parse_int(const gchar *s, long *d)
   return TRUE;
 }
 
+static gboolean
+tf_num_parse(gint argc, GString *argv[],
+	     const gchar *func_name, glong *n, glong *m)
+{
+  if (argc != 2)
+    {
+      msg_error("Template function requires two arguments.",
+		evt_tag_str("function", func_name), NULL);
+      return FALSE;
+    }
+
+  if (!tf_parse_int(argv[0]->str, n))
+    {
+      msg_error("Parsing failed, template function's first argument is not a number",
+		evt_tag_str("function", func_name),
+		evt_tag_str("arg1", argv[0]->str), NULL);
+      return FALSE;
+    }
+
+  if (!tf_parse_int(argv[1]->str, m))
+    {
+      msg_error("Parsing failed, template function's first argument is not a number",
+		evt_tag_str("function", func_name),
+		evt_tag_str("arg1", argv[1]->str), NULL);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static void
+tf_num_plus(LogMessage *msg, gint argc, GString *argv[], GString *result)
+{
+  glong n, m;
+
+  if (!tf_num_parse(argc, argv, "+", &n, &m))
+    return;
+
+  g_string_append_printf(result, "%li", n + m);
+}
+
+TEMPLATE_FUNCTION_SIMPLE(tf_num_plus);
+
+static void
+tf_num_minus(LogMessage *msg, gint argc, GString *argv[], GString *result)
+{
+  glong n, m;
+
+  if (!tf_num_parse(argc, argv, "-", &n, &m))
+    return;
+
+  g_string_append_printf(result, "%li", n - m);
+}
+
+TEMPLATE_FUNCTION_SIMPLE(tf_num_minus);
+
+static void
+tf_num_multi(LogMessage *msg, gint argc, GString *argv[], GString *result)
+{
+  glong n, m;
+
+  if (!tf_num_parse(argc, argv, "*", &n, &m))
+    return;
+
+  g_string_append_printf(result, "%li", n * m);
+}
+
+TEMPLATE_FUNCTION_SIMPLE(tf_num_multi);
+
+static void
+tf_num_div(LogMessage *msg, gint argc, GString *argv[], GString *result)
+{
+  glong n, m;
+
+  if (!tf_num_parse(argc, argv, "/", &n, &m))
+    return;
+
+  if (m == 0)
+    {
+      msg_error ("$(/): Division by zero in the template function",
+		 NULL);
+      return;
+    }
+
+  g_string_append_printf(result, "%li", (glong)(n / m));
+}
+
+TEMPLATE_FUNCTION_SIMPLE(tf_num_div);
+
+static void
+tf_num_mod(LogMessage *msg, gint argc, GString *argv[], GString *result)
+{
+  glong n, m;
+
+  if (!tf_num_parse(argc, argv, "%", &n, &m))
+    return;
+
+  if (m == 0)
+    {
+      msg_error ("$(%): Division by zero in the template function",
+		 NULL);
+      return;
+    }
+
+  g_string_append_printf(result, "%li", n % m);
+}
+
+TEMPLATE_FUNCTION_SIMPLE(tf_num_mod);
+
 static void
 tf_substr(LogMessage *msg, gint argc, GString *argv[], GString *result)
 {
@@ -64,14 +173,14 @@ tf_substr(LogMessage *msg, gint argc, GString *argv[], GString *result)
     return;
 
   /* get offset position from second argument */
-  if (!tf_substr_parse_int(argv[1]->str, &start)) {
+  if (!tf_parse_int(argv[1]->str, &start)) {
     msg_error("$(substr) parsing failed, start could not be parsed", evt_tag_str("start", argv[1]->str), NULL);
     return;
   }
 
   /* if we were called with >2 arguments, third was desired length */
   if (argc > 2) {
-    if (!tf_substr_parse_int(argv[2]->str, &len)) {
+    if (!tf_parse_int(argv[2]->str, &len)) {
       msg_error("$(substr) parsing failed, length could not be parsed", evt_tag_str("length", argv[2]->str), NULL);
       return;
     }
@@ -282,6 +391,11 @@ static Plugin basicfuncs_plugins[] =
   TEMPLATE_FUNCTION_PLUGIN(tf_grep, "grep"),
   TEMPLATE_FUNCTION_PLUGIN(tf_if, "if"),
   TEMPLATE_FUNCTION_PLUGIN(tf_substr, "substr"),
+  TEMPLATE_FUNCTION_PLUGIN(tf_num_plus, "+"),
+  TEMPLATE_FUNCTION_PLUGIN(tf_num_minus, "-"),
+  TEMPLATE_FUNCTION_PLUGIN(tf_num_multi, "*"),
+  TEMPLATE_FUNCTION_PLUGIN(tf_num_div, "/"),
+  TEMPLATE_FUNCTION_PLUGIN(tf_num_mod, "%"),
 };
 
 gboolean
diff --git a/tests/unit/test_template.c b/tests/unit/test_template.c
index fca0076..aabc3db 100644
--- a/tests/unit/test_template.c
+++ b/tests/unit/test_template.c
@@ -246,6 +246,15 @@ main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED)
   testcase(msg, "$(substr $HOST -1)", "p");
   testcase(msg, "$(substr $HOST -2 1)", "r");
 
+  testcase(msg, "$(+ $FACILITY_NUM 1)", "20");
+  testcase(msg, "$(- $FACILITY_NUM 1)", "18");
+  testcase(msg, "$(* $FACILITY_NUM 2)", "38");
+  testcase(msg, "$(/ $FACILITY_NUM 2)", "9");
+  testcase(msg, "$(% $FACILITY_NUM 3)", "1");
+  testcase(msg, "$(/ $FACILITY_NUM 0)", "");
+  testcase(msg, "$(% $FACILITY_NUM 0)", "");
+  testcase(msg, "$(+ foo bar)", "");
+
   /* message refs */
   testcase(msg, "$(echo ${HOST}@0 ${PID}@1)", "bzorp 23323");
   testcase(msg, "$(echo $HOST $PID)@0", "bzorp 23323");
-- 
1.7.2.5




More information about the syslog-ng mailing list