diff options
-rw-r--r-- | ChangeLog.d/feature/ZBXNEXT-6184 | 1 | ||||
-rw-r--r-- | include/common.h | 18 | ||||
-rw-r--r-- | include/zbxtypes.h | 4 | ||||
-rw-r--r-- | src/libs/zbxcommon/Makefile.am | 3 | ||||
-rw-r--r-- | src/libs/zbxcommon/str.c | 58 | ||||
-rw-r--r-- | src/libs/zbxcommon/time.c | 274 | ||||
-rw-r--r-- | src/libs/zbxserver/expression.c | 73 | ||||
-rw-r--r-- | src/libs/zbxserver/macrofunc.c | 129 |
8 files changed, 531 insertions, 29 deletions
diff --git a/ChangeLog.d/feature/ZBXNEXT-6184 b/ChangeLog.d/feature/ZBXNEXT-6184 new file mode 100644 index 00000000000..944ae9533f7 --- /dev/null +++ b/ChangeLog.d/feature/ZBXNEXT-6184 @@ -0,0 +1 @@ +........S. [ZBXNEXT-6184] added formatting macro functions fmttime and fmtnum (viktors, wiper) diff --git a/include/common.h b/include/common.h index ae29dfec97b..ae6a82f7db5 100644 --- a/include/common.h +++ b/include/common.h @@ -1093,6 +1093,7 @@ time_t calculate_proxy_nextcheck(zbx_uint64_t hostid, unsigned int delay, time_t int zbx_check_time_period(const char *period, time_t time, const char *tz, int *res); void zbx_hex2octal(const char *input, char **output, int *olen); int str_in_list(const char *list, const char *value, char delimiter); +int str_n_in_list(const char *list, const char *value, size_t len, char delimiter); char *str_linefeed(const char *src, size_t maxline, const char *delim); void zbx_strarr_init(char ***arr); void zbx_strarr_add(char ***arr, const char *entry); @@ -1652,4 +1653,21 @@ int zbx_str_extract(const char *text, size_t len, char **value); #define AUDIT_ACTION_EXECUTE 7 #define AUDIT_RESOURCE_SCRIPT 25 +typedef enum +{ + ZBX_TIME_UNIT_UNKNOWN, + ZBX_TIME_UNIT_HOUR, + ZBX_TIME_UNIT_DAY, + ZBX_TIME_UNIT_WEEK, + ZBX_TIME_UNIT_MONTH, + ZBX_TIME_UNIT_YEAR +} +zbx_time_unit_t; + +void zbx_tm_add(struct tm *tm, int multiplier, zbx_time_unit_t base); +void zbx_tm_sub(struct tm *tm, int multiplier, zbx_time_unit_t base); + +zbx_time_unit_t zbx_tm_str_to_unit(const char *text); +int zbx_tm_parse_period(const char *period, size_t *len, int *multiplier, zbx_time_unit_t *base, char **error); + #endif diff --git a/include/zbxtypes.h b/include/zbxtypes.h index 0d3a5b421ed..9495e412e7e 100644 --- a/include/zbxtypes.h +++ b/include/zbxtypes.h @@ -214,4 +214,8 @@ zbx_uint128_t; /* macro to test if a signed value has been assigned to unsigned type (char, short, int, long long) */ #define ZBX_IS_TOP_BIT_SET(x) (0 != ((__UINT64_C(1) << ((sizeof(x) << 3) - 1)) & (x))) +#if defined(_WINDOWS) + #define localtime_r(x, y) localtime_s(y, x) +#endif + #endif diff --git a/src/libs/zbxcommon/Makefile.am b/src/libs/zbxcommon/Makefile.am index dda144eff47..221a9a93ab3 100644 --- a/src/libs/zbxcommon/Makefile.am +++ b/src/libs/zbxcommon/Makefile.am @@ -13,6 +13,7 @@ libzbxcommon_a_SOURCES = \ variant.c \ variant_misc.c \ xml.c \ - zbxgetopt.c + zbxgetopt.c \ + time.c libzbxcommon_a_CFLAGS = $(ICONV_CFLAGS) diff --git a/src/libs/zbxcommon/str.c b/src/libs/zbxcommon/str.c index b9f4e736825..425da0c83b0 100644 --- a/src/libs/zbxcommon/str.c +++ b/src/libs/zbxcommon/str.c @@ -5337,42 +5337,66 @@ void remove_param(char *param, int num) /****************************************************************************** * * - * Function: str_in_list * + * Function: str_n_in_list * * * * Purpose: check if string is contained in a list of delimited strings * * * - * Parameters: list - strings a,b,ccc,ddd * - * value - value * - * delimiter - delimiter * + * Parameters: list - [IN] strings a,b,ccc,ddd * + * value - [IN] value * + * len - [IN] value length * + * delimiter - [IN] delimiter * * * * Return value: SUCCEED - string is in the list, FAIL - otherwise * * * - * Author: Alexei Vladishev, Aleksandrs Saveljevs * - * * ******************************************************************************/ -int str_in_list(const char *list, const char *value, char delimiter) +int str_n_in_list(const char *list, const char *value, size_t len, char delimiter) { const char *end; - int ret = FAIL; - size_t len; + size_t token_len, next = 1; - len = strlen(value); - - while (SUCCEED != ret) + while ('\0' != *list) { if (NULL != (end = strchr(list, delimiter))) { - ret = (len == (size_t)(end - list) && 0 == strncmp(list, value, len) ? SUCCEED : FAIL); - list = end + 1; + token_len = end - list; + next = 1; } else { - ret = (0 == strcmp(list, value) ? SUCCEED : FAIL); - break; + token_len = strlen(list); + next = 0; } + + if (len == token_len && 0 == memcmp(list, value, len)) + return SUCCEED; + + list += token_len + next; } - return ret; + if (1 == next && 0 == len) + return SUCCEED; + + return FAIL; +} + +/****************************************************************************** + * * + * Function: str_in_list * + * * + * Purpose: check if string is contained in a list of delimited strings * + * * + * Parameters: list - strings a,b,ccc,ddd * + * value - value * + * delimiter - delimiter * + * * + * Return value: SUCCEED - string is in the list, FAIL - otherwise * + * * + * Author: Alexei Vladishev, Aleksandrs Saveljevs * + * * + ******************************************************************************/ +int str_in_list(const char *list, const char *value, char delimiter) +{ + return str_n_in_list(list, value, strlen(value), delimiter); } /****************************************************************************** diff --git a/src/libs/zbxcommon/time.c b/src/libs/zbxcommon/time.c new file mode 100644 index 00000000000..187ffcb5315 --- /dev/null +++ b/src/libs/zbxcommon/time.c @@ -0,0 +1,274 @@ +/* +** Zabbix +** Copyright (C) 2001-2020 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program 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 General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + +#include "common.h" + +static void tm_sub(struct tm *tm, int multiplier, zbx_time_unit_t base); + +zbx_time_unit_t zbx_tm_str_to_unit(const char *text) +{ + switch (*text) + { + case 'h': + return ZBX_TIME_UNIT_HOUR; + case 'd': + return ZBX_TIME_UNIT_DAY; + case 'w': + return ZBX_TIME_UNIT_WEEK; + case 'M': + return ZBX_TIME_UNIT_MONTH; + case 'y': + return ZBX_TIME_UNIT_YEAR; + default: + return ZBX_TIME_UNIT_UNKNOWN; + } +} + +/****************************************************************************** + * * + * Function: zbx_tm_parse_period * + * * + * Purpose: parse time period in format <multiplier><time unit> * + * * + * Parameters: period - [IN] the time period * + * len - [OUT] the length of parsed time period * + * multiplier - [OUT] the parsed multiplier * + * base - [OUT] the parsed time unit * + * error - [OUT] the error message if parsing failed * + * * + * Return value: SUCCEED - period was parsed successfully * + * FAIL - invalid time period was specified * + * * + ******************************************************************************/ +int zbx_tm_parse_period(const char *period, size_t *len, int *multiplier, zbx_time_unit_t *base, char **error) +{ + const char *ptr; + + for (ptr = period; 0 != isdigit(*ptr); ptr++) + ; + + if (FAIL == is_uint_n_range(period, ptr - period, multiplier, sizeof(*multiplier), 1, UINT32_MAX)) + { + *error = zbx_strdup(*error, "invalid period multiplier"); + return FAIL; + } + + if (ZBX_TIME_UNIT_UNKNOWN == (*base = zbx_tm_str_to_unit(ptr))) + { + *error = zbx_strdup(*error, "invalid period time unit"); + return FAIL; + } + + *len = ptr - period + 1; + + return SUCCEED; +} + +/****************************************************************************** + * * + * Function: tm_add * + * * + * Purpose: add time duration without adjusting DST clocks * + * * + * Parameter: tm - [IN/OUT] the time structure * + * multiplier - [IN] the unit multiplier * + * base - [IN] the time unit to add * + * * + ******************************************************************************/ +static void tm_add(struct tm *tm, int multiplier, zbx_time_unit_t base) +{ + int shift; + + switch (base) + { + case ZBX_TIME_UNIT_HOUR: + tm->tm_hour += multiplier; + if (24 <= tm->tm_hour) + { + shift = tm->tm_hour / 24; + tm->tm_hour %= 24; + tm_add(tm, shift, ZBX_TIME_UNIT_DAY); + } + break; + case ZBX_TIME_UNIT_DAY: + tm->tm_mday += multiplier; + while (tm->tm_mday > (shift = zbx_day_in_month(tm->tm_year + 1900, tm->tm_mon + 1))) + { + tm->tm_mday -= shift; + tm_add(tm, 1, ZBX_TIME_UNIT_MONTH); + } + tm->tm_wday += multiplier; + tm->tm_wday %= 7; + break; + case ZBX_TIME_UNIT_WEEK: + tm_add(tm, multiplier * 7, ZBX_TIME_UNIT_DAY); + break; + case ZBX_TIME_UNIT_MONTH: + tm->tm_mon += multiplier; + if (12 <= tm->tm_mon) + { + shift = tm->tm_mon / 12; + tm->tm_mon %= 12; + tm_add(tm, shift, ZBX_TIME_UNIT_YEAR); + } + break; + case ZBX_TIME_UNIT_YEAR: + tm->tm_year += multiplier; + break; + default: + break; + } +} + +/****************************************************************************** + * * + * Function: zbx_tm_add * + * * + * Purpose: add time duration * + * * + * Parameter: tm - [IN/OUT] the time structure * + * multiplier - [IN] the unit multiplier * + * base - [IN] the time unit to add * + * * + ******************************************************************************/ +void zbx_tm_add(struct tm *tm, int multiplier, zbx_time_unit_t base) +{ + time_t time_new; + struct tm tm_new; + + tm_add(tm, multiplier, base); + + /* adjust clock if DST changes were in effect */ + + tm_new = *tm; + + if (-1 != (time_new = mktime(&tm_new))) + { + tm_new = *localtime(&time_new); + if (tm->tm_isdst != tm_new.tm_isdst && -1 != tm->tm_isdst && -1 != tm_new.tm_isdst) + { + *tm = tm_new; + if (0 == tm->tm_isdst) + tm_add(tm, 1, ZBX_TIME_UNIT_HOUR); + else + tm_sub(tm, 1, ZBX_TIME_UNIT_HOUR); + } + } +} + +/****************************************************************************** + * * + * Function: tm_sub * + * * + * Purpose: subtracts time duration without adjusting DST clocks * + * * + * Parameter: tm - [IN/OUT] the time structure * + * multiplier - [IN] the unit multiplier * + * base - [IN] the time unit to add * + * * + ******************************************************************************/ +static void tm_sub(struct tm *tm, int multiplier, zbx_time_unit_t base) +{ + int shift; + + switch (base) + { + case ZBX_TIME_UNIT_HOUR: + tm->tm_hour -= multiplier; + if (0 > tm->tm_hour) + { + shift = -tm->tm_hour / 24 + 1; + tm->tm_hour = 24 + tm->tm_hour % 24; + tm_sub(tm, shift, ZBX_TIME_UNIT_DAY); + } + return; + case ZBX_TIME_UNIT_DAY: + tm->tm_mday -= multiplier; + while (0 >= tm->tm_mday) + { + int prev_mon; + + if (0 > (prev_mon = tm->tm_mon - 1)) + prev_mon = 11; + prev_mon++; + + tm->tm_mday += zbx_day_in_month(tm->tm_year + 1900, prev_mon); + tm_sub(tm, 1, ZBX_TIME_UNIT_MONTH); + } + tm->tm_wday -= multiplier; + if (0 < tm->tm_wday) + tm->tm_wday = 7 + tm->tm_wday % 7; + return; + case ZBX_TIME_UNIT_WEEK: + tm_sub(tm, multiplier * 7, ZBX_TIME_UNIT_DAY); + return; + case ZBX_TIME_UNIT_MONTH: + tm->tm_mon -= multiplier; + if (0 > tm->tm_mon) + { + shift = -tm->tm_mon / 12 + 1; + tm->tm_mon = 12 + tm->tm_mon % 12; + tm_sub(tm, shift, ZBX_TIME_UNIT_YEAR); + } + return; + case ZBX_TIME_UNIT_YEAR: + tm->tm_year -= multiplier; + return; + default: + return; + } +} + +/****************************************************************************** + * * + * Function: zbx_tm_sub * + * * + * Purpose: subtracts time duration * + * * + * Parameter: tm - [IN/OUT] the time structure * + * multiplier - [IN] the unit multiplier * + * base - [IN] the time unit to add * + * * + ******************************************************************************/ +void zbx_tm_sub(struct tm *tm, int multiplier, zbx_time_unit_t base) +{ + time_t time_new; + struct tm tm_new; + + tm_sub(tm, multiplier, base); + + /* adjust clock if DST changes were in effect */ + + tm_new = *tm; + + if (-1 != (time_new = mktime(&tm_new))) + { + tm_new = *localtime(&time_new); + + if (tm->tm_isdst != tm_new.tm_isdst && -1 != tm->tm_isdst && -1 != tm_new.tm_isdst) + { + *tm = tm_new; + if (0 == tm->tm_isdst) + tm_add(tm, 1, ZBX_TIME_UNIT_HOUR); + else + tm_sub(tm, 1, ZBX_TIME_UNIT_HOUR); + + } + } +} diff --git a/src/libs/zbxserver/expression.c b/src/libs/zbxserver/expression.c index 0f295bb5ee5..d6639575738 100644 --- a/src/libs/zbxserver/expression.c +++ b/src/libs/zbxserver/expression.c @@ -2054,8 +2054,22 @@ static const char *ex_macros[] = static const char *simple_host_macros[] = {MVAR_HOST_HOST, MVAR_HOSTNAME, NULL}; static const char *simple_key_macros[] = {MVAR_ITEM_KEY, MVAR_TRIGGER_KEY, NULL}; +typedef struct +{ + char *macro; + char *functions; +} +zbx_macro_functions_t; + /* macros that can be modified using macro functions */ -static const char *mod_macros[] = {MVAR_ITEM_VALUE, MVAR_ITEM_LASTVALUE, NULL}; +static zbx_macro_functions_t mod_macros[] = +{ + {MVAR_ITEM_VALUE, "regsub,iregsub,fmtnum"}, + {MVAR_ITEM_LASTVALUE, "regsub,iregsub,fmtnum"}, + {MVAR_TIME, "fmttime"}, + {"?", "fmtnum"}, + {NULL, NULL} +}; typedef struct { @@ -2658,6 +2672,54 @@ static const char *macro_in_list(const char *str, zbx_strloc_t strloc, const cha /****************************************************************************** * * + * Function: func_macro_in_list * + * * + * Purpose: check if a macro function one in the list for the macro * + * * + * Parameters: str - [IN] string containing potential macro * + * fm - [IN] function macro to check * + * N_functionid - [OUT] index of the macro in string (if valid) * + * * + * Return value: unindexed macro from the allowed list or NULL * + * * + ******************************************************************************/ +static const char *func_macro_in_list(const char *str, zbx_token_func_macro_t *fm, int *N_functionid) +{ + int i; + + for (i = 0; NULL != mod_macros[i].macro; i++) + { + size_t len, fm_len; + + len = strlen(mod_macros[i].macro); + fm_len = fm->macro.r - fm->macro.l + 1; + + if (len > fm_len || 0 != strncmp(mod_macros[i].macro, str + fm->macro.l, len - 1)) + continue; + + if (len != fm_len) + { + if (SUCCEED != is_uint_n_range(str + fm->macro.l + len - 1, fm_len - len, N_functionid, + sizeof(*N_functionid), 1, 9)) + { + continue; + } + } + else if (mod_macros[i].macro[len - 1] != str[fm->macro.l + len - 1]) + continue; + + if (SUCCEED == str_n_in_list(mod_macros[i].functions, str + fm->func.l, fm->func_param.l - fm->func.l, + ',')) + { + return mod_macros[i].macro; + } + } + + return NULL; +} + +/****************************************************************************** + * * * Function: get_trigger_function_value * * * * Purpose: trying to evaluate a trigger function * @@ -2982,8 +3044,7 @@ static int substitute_simple_macros_impl(zbx_uint64_t *actionid, const DB_EVENT case ZBX_TOKEN_FUNC_MACRO: raw_value = 1; indexed_macro = is_indexed_macro(*data, &token); - if (NULL == (m = macro_in_list(*data, token.data.func_macro.macro, mod_macros, - &N_functionid))) + if (NULL == (m = func_macro_in_list(*data, &token.data.func_macro, &N_functionid))) { /* Ignore functions with macros not supporting them, but do not skip the */ /* whole token, nested macro should be resolved in this case. */ @@ -3215,7 +3276,7 @@ static int substitute_simple_macros_impl(zbx_uint64_t *actionid, const DB_EVENT ret = DBget_trigger_value(c_event->trigger.expression, &replace_to, N_functionid, ZBX_REQUEST_PROXY_DESCRIPTION); } - else if (0 == strcmp(m, MVAR_TIME)) + else if (0 == indexed_macro && 0 == strcmp(m, MVAR_TIME)) { replace_to = zbx_strdup(replace_to, zbx_time2str(time(NULL), tz)); } @@ -3464,7 +3525,7 @@ static int substitute_simple_macros_impl(zbx_uint64_t *actionid, const DB_EVENT ret = DBget_trigger_value(c_event->trigger.expression, &replace_to, N_functionid, ZBX_REQUEST_PROXY_DESCRIPTION); } - else if (0 == strcmp(m, MVAR_TIME)) + else if (0 == indexed_macro && 0 == strcmp(m, MVAR_TIME)) { replace_to = zbx_strdup(replace_to, zbx_time2str(time(NULL), tz)); } @@ -5903,7 +5964,7 @@ int substitute_lld_macros(char **data, const struct zbx_json_parse *jp_row, cons pos = token.loc.r; break; case ZBX_TOKEN_FUNC_MACRO: - if (NULL != macro_in_list(*data, token.data.func_macro.macro, mod_macros, NULL)) + if (NULL != func_macro_in_list(*data, &token.data.func_macro, NULL)) { ret = substitute_func_macro(data, &token, jp_row, lld_macro_paths, error, max_error_len); diff --git a/src/libs/zbxserver/macrofunc.c b/src/libs/zbxserver/macrofunc.c index 12eaf90f345..97f40f5cb68 100644 --- a/src/libs/zbxserver/macrofunc.c +++ b/src/libs/zbxserver/macrofunc.c @@ -20,6 +20,7 @@ #include "common.h" #include "zbxregexp.h" #include "macrofunc.h" +#include "log.h" /****************************************************************************** * * @@ -27,8 +28,9 @@ * * * Purpose: calculates regular expression substitution * * * - * Parameters: func - [IN] the function data * - * out - [IN/OUT] the input/output value * + * Parameters: params - [IN] the function parameters * + * nparam - [IN] the function parameter count * + * out - [IN/OUT] the input/output value * * * * Return value: SUCCEED - the function was calculated successfully. * * FAIL - the function calculation failed. * @@ -59,8 +61,9 @@ static int macrofunc_regsub(char **params, size_t nparam, char **out) * * * Purpose: calculates case insensitive regular expression substitution * * * - * Parameters: func - [IN] the function data * - * out - [IN/OUT] the input/output value * + * Parameters: params - [IN] the function parameters * + * nparam - [IN] the function parameter count * + * out - [IN/OUT] the input/output value * * * * Return value: SUCCEED - the function was calculated successfully. * * FAIL - the function calculation failed. * @@ -87,6 +90,115 @@ static int macrofunc_iregsub(char **params, size_t nparam, char **out) /****************************************************************************** * * + * Function: macrofunc_fmttime * + * * + * Purpose: time formatting macro function * + * * + * Parameters: params - [IN] the function parameters * + * nparam - [IN] the function parameter count * + * out - [IN/OUT] the input/output value * + * * + * Return value: SUCCEED - the function was calculated successfully. * + * FAIL - the function calculation failed. * + * * + ******************************************************************************/ +static int macrofunc_fmttime(char **params, size_t nparam, char **out) +{ + struct tm local_time; + time_t time_new; + char *buf = NULL; + + if (0 == nparam || 2 < nparam) + return FAIL; + + time_new = time(&time_new); + localtime_r(&time_new, &local_time); + + if (2 == nparam) + { + char *period = params[1], *error = NULL; + int period_num; + zbx_time_unit_t base; + size_t len; + + /* second parameter must start with a negative sign, contain a value and end with a time unit */ + if ('-' != period[0] || 2 >= strlen(period)) + { + zabbix_log(LOG_LEVEL_DEBUG, "invalid second parameter \"%s\"", params[1]); + return FAIL; + } + + if (FAIL == zbx_tm_parse_period(++period, &len, &period_num, &base, &error) || '\0' != period[len]) + { + zabbix_log(LOG_LEVEL_DEBUG, "cannot parse second parameter \"%s\": %s", params[1], + ZBX_NULL2STR(error)); + + zbx_free(error); + return FAIL; + } + + zbx_tm_sub(&local_time, period_num, base); + } + + buf = zbx_malloc(NULL, MAX_STRING_LEN); + + if (0 == strftime(buf, MAX_STRING_LEN, params[0], &local_time)) + { + zabbix_log(LOG_LEVEL_DEBUG, "invalid first parameter \"%s\"", params[0]); + zbx_free(buf); + return FAIL; + } + + zbx_free(*out); + *out = buf; + + return SUCCEED; +} + +/****************************************************************************** + * * + * Function: macrofunc_fmtnum * + * * + * Purpose: number formatting macro function * + * * + * Parameters: params - [IN] the function data * + * nparam - [IN] parameter count * + * out - [IN/OUT] the input/output value * + * * + * Return value: SUCCEED - the function was calculated successfully. * + * FAIL - the function calculation failed. * + * * + ******************************************************************************/ +static int macrofunc_fmtnum(char **params, size_t nparam, char **out) +{ + double value; + int precision; + + if (1 != nparam) + return FAIL; + + if (SUCCEED == is_uint32(*out, &value)) + return SUCCEED; + + if (FAIL == is_double(*out, &value)) + { + zabbix_log(LOG_LEVEL_DEBUG, "macro \"%s\" is not a number", *out); + return FAIL; + } + + if (FAIL == is_uint32(params[0], &precision)) + { + zabbix_log(LOG_LEVEL_DEBUG, "invalid parameter \"%s\"", params[0]); + return FAIL; + } + + *out = zbx_dsprintf(*out, "%.*f", precision, value); + + return SUCCEED; +} + +/****************************************************************************** + * * * Function: zbx_calculate_macro_function * * * * Purpose: calculates macro function value * @@ -106,6 +218,8 @@ int zbx_calculate_macro_function(const char *expression, const zbx_token_func_ma size_t nparam = 0, param_alloc = 8, buf_alloc = 0, buf_offset = 0, len, sep_pos; int (*macrofunc)(char **params, size_t nparam, char **out), ret; + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + ptr = expression + func_macro->func.l; len = func_macro->func_param.l - func_macro->func.l; @@ -113,6 +227,10 @@ int zbx_calculate_macro_function(const char *expression, const zbx_token_func_ma macrofunc = macrofunc_regsub; else if (ZBX_CONST_STRLEN("iregsub") == len && 0 == strncmp(ptr, "iregsub", len)) macrofunc = macrofunc_iregsub; + else if (ZBX_CONST_STRLEN("fmttime") == len && 0 == strncmp(ptr, "fmttime", len)) + macrofunc = macrofunc_fmttime; + else if (ZBX_CONST_STRLEN("fmtnum") == len && 0 == strncmp(ptr, "fmtnum", len)) + macrofunc = macrofunc_fmtnum; else return FAIL; @@ -143,6 +261,7 @@ int zbx_calculate_macro_function(const char *expression, const zbx_token_func_ma zbx_free(params); zbx_free(buf); + zabbix_log(LOG_LEVEL_DEBUG, "End of %s(), ret: %s", __func__, zbx_result_string(ret)); + return ret; } - |