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@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