mirror of
https://github.com/rsyslog/rsyslog.git
synced 2025-12-20 02:40:42 +01:00
Merge pull request #2185 from rgerhards/i-1978
RainerScript: add function script_error() and error-reporting support
This commit is contained in:
commit
4af883651e
@ -1499,7 +1499,7 @@ finalize_it:
|
||||
}
|
||||
|
||||
static void
|
||||
doFunc_re_extract(struct cnffunc *func, struct svar *ret, void* usrptr)
|
||||
doFunc_re_extract(struct cnffunc *func, struct svar *ret, void* usrptr, wti_t *const pWti)
|
||||
{
|
||||
size_t submatchnbr;
|
||||
short matchnbr;
|
||||
@ -1515,12 +1515,12 @@ doFunc_re_extract(struct cnffunc *func, struct svar *ret, void* usrptr)
|
||||
iOffs = 0;
|
||||
sbool bHadNoMatch = 0;
|
||||
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr);
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr, pWti);
|
||||
/* search string is already part of the compiled regex, so we don't
|
||||
* need it here!
|
||||
*/
|
||||
cnfexprEval(func->expr[2], &r[2], usrptr);
|
||||
cnfexprEval(func->expr[3], &r[3], usrptr);
|
||||
cnfexprEval(func->expr[2], &r[2], usrptr, pWti);
|
||||
cnfexprEval(func->expr[3], &r[3], usrptr, pWti);
|
||||
str = (char*) var2CString(&r[0], &bMustFree);
|
||||
matchnbr = (short) var2Number(&r[2], NULL);
|
||||
submatchnbr = (size_t) var2Number(&r[3], NULL);
|
||||
@ -1579,7 +1579,7 @@ finalize_it:
|
||||
varFreeMembers(&r[3]);
|
||||
|
||||
if(bHadNoMatch) {
|
||||
cnfexprEval(func->expr[4], &r[4], usrptr);
|
||||
cnfexprEval(func->expr[4], &r[4], usrptr, pWti);
|
||||
estr = var2String(&r[4], &bMustFree);
|
||||
varFreeMembersSelectively(&r[4], SKIP_STRING);
|
||||
/* Note that we do NOT free the string that was returned/created
|
||||
@ -1900,9 +1900,10 @@ estimateYear(int cy, int cm, int im) {
|
||||
/* Perform a function call. This has been moved out of cnfExprEval in order
|
||||
* to keep the code small and easier to maintain.
|
||||
*/
|
||||
static void
|
||||
static void ATTR_NONNULL()
|
||||
doFuncCall(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret,
|
||||
void *__restrict__ const usrptr)
|
||||
void *__restrict__ const usrptr,
|
||||
wti_t *__restrict__ const pWti)
|
||||
{
|
||||
char *envvar;
|
||||
int bMustFree;
|
||||
@ -1928,7 +1929,7 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct svar *__restrict__ co
|
||||
*/
|
||||
ret->d.n = es_strlen(((struct cnfstringval*) func->expr[0])->estr);
|
||||
} else {
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr);
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr, pWti);
|
||||
estr = var2String(&r[0], &bMustFree);
|
||||
ret->d.n = es_strlen(estr);
|
||||
if(bMustFree) es_deleteStr(estr);
|
||||
@ -1937,9 +1938,9 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct svar *__restrict__ co
|
||||
ret->datatype = 'N';
|
||||
break;
|
||||
case CNFFUNC_REPLACE:
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr);
|
||||
cnfexprEval(func->expr[1], &r[1], usrptr);
|
||||
cnfexprEval(func->expr[2], &r[2], usrptr);
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr, pWti);
|
||||
cnfexprEval(func->expr[1], &r[1], usrptr, pWti);
|
||||
cnfexprEval(func->expr[2], &r[2], usrptr, pWti);
|
||||
ret->d.estr = doFuncReplace(&r[0], &r[1], &r[2]);
|
||||
ret->datatype = 'S';
|
||||
varFreeMembers(&r[0]);
|
||||
@ -1947,9 +1948,9 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct svar *__restrict__ co
|
||||
varFreeMembers(&r[2]);
|
||||
break;
|
||||
case CNFFUNC_WRAP:
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr);
|
||||
cnfexprEval(func->expr[1], &r[1], usrptr);
|
||||
if(func->nParams == 3) cnfexprEval(func->expr[2], &r[2], usrptr);
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr, pWti);
|
||||
cnfexprEval(func->expr[1], &r[1], usrptr, pWti);
|
||||
if(func->nParams == 3) cnfexprEval(func->expr[2], &r[2], usrptr, pWti);
|
||||
ret->d.estr = doFuncWrap(&r[0], &r[1], func->nParams > 2 ? &r[2] : NULL);
|
||||
ret->datatype = 'S';
|
||||
varFreeMembers(&r[0]);
|
||||
@ -1957,19 +1958,19 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct svar *__restrict__ co
|
||||
if(func->nParams == 3) varFreeMembers(&r[2]);
|
||||
break;
|
||||
case CNFFUNC_RANDOM:
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr);
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr, pWti);
|
||||
ret->d.n = doRandomGen(&r[0]);
|
||||
ret->datatype = 'N';
|
||||
varFreeMembers(&r[0]);
|
||||
break;
|
||||
case CNFFUNC_NUM2IPV4:
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr);
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr, pWti);
|
||||
ret->d.estr = num2ipv4(&r[0]);
|
||||
ret->datatype = 'S';
|
||||
varFreeMembers(&r[0]);
|
||||
break;
|
||||
case CNFFUNC_LTRIM:
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr);
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr, pWti);
|
||||
str = (char*)var2CString(&r[0], &bMustFree);
|
||||
ret->datatype = 'S';
|
||||
ret->d.estr = lTrim(str);
|
||||
@ -1978,7 +1979,7 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct svar *__restrict__ co
|
||||
free(str);
|
||||
break;
|
||||
case CNFFUNC_RTRIM:
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr);
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr, pWti);
|
||||
str = (char*)var2CString(&r[0], &bMustFree);
|
||||
ret->datatype = 'S';
|
||||
ret->d.estr = rTrim(str);
|
||||
@ -1992,7 +1993,7 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct svar *__restrict__ co
|
||||
* getenv()). So we do NOT need to check if there is just a
|
||||
* string following.
|
||||
*/
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr);
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr, pWti);
|
||||
estr = var2String(&r[0], &bMustFree);
|
||||
str = (char*) es_str2cstr(estr, NULL);
|
||||
envvar = getenv(str);
|
||||
@ -2007,7 +2008,7 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct svar *__restrict__ co
|
||||
free(str);
|
||||
break;
|
||||
case CNFFUNC_TOLOWER:
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr);
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr, pWti);
|
||||
estr = var2String(&r[0], &bMustFree);
|
||||
if(!bMustFree) /* let caller handle that M) */
|
||||
estr = es_strdup(estr);
|
||||
@ -2017,7 +2018,7 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct svar *__restrict__ co
|
||||
varFreeMembers(&r[0]);
|
||||
break;
|
||||
case CNFFUNC_CSTR:
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr);
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr, pWti);
|
||||
estr = var2String(&r[0], &bMustFree);
|
||||
if(!bMustFree) /* let caller handle that M) */
|
||||
estr = es_strdup(estr);
|
||||
@ -2026,7 +2027,7 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct svar *__restrict__ co
|
||||
varFreeMembers(&r[0]);
|
||||
break;
|
||||
case CNFFUNC_IPV42NUM:
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr);
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr, pWti);
|
||||
str = (char*)var2CString(&r[0], &bMustFree);
|
||||
ret->datatype = 'N';
|
||||
ret->d.n = ipv42num(str);
|
||||
@ -2041,7 +2042,7 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct svar *__restrict__ co
|
||||
ret->d.n = es_str2num(((struct cnfstringval*) func->expr[0])->estr,
|
||||
NULL);
|
||||
} else {
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr);
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr, pWti);
|
||||
ret->d.n = var2Number(&r[0], NULL);
|
||||
varFreeMembers(&r[0]);
|
||||
}
|
||||
@ -2049,7 +2050,7 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct svar *__restrict__ co
|
||||
DBGPRINTF("JSONorString: cnum node type %c result %d\n", func->expr[0]->nodetype, (int) ret->d.n);
|
||||
break;
|
||||
case CNFFUNC_RE_MATCH:
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr);
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr, pWti);
|
||||
str = (char*) var2CString(&r[0], &bMustFree);
|
||||
retval = regexp.regexec(func->funcdata, str, 0, NULL, 0);
|
||||
if(retval == 0)
|
||||
@ -2065,15 +2066,15 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct svar *__restrict__ co
|
||||
varFreeMembers(&r[0]);
|
||||
break;
|
||||
case CNFFUNC_RE_EXTRACT:
|
||||
doFunc_re_extract(func, ret, usrptr);
|
||||
doFunc_re_extract(func, ret, usrptr, pWti);
|
||||
break;
|
||||
case CNFFUNC_EXEC_TEMPLATE:
|
||||
doFunc_exec_template(func, ret, (smsg_t*) usrptr);
|
||||
break;
|
||||
case CNFFUNC_FIELD:
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr);
|
||||
cnfexprEval(func->expr[1], &r[1], usrptr);
|
||||
cnfexprEval(func->expr[2], &r[2], usrptr);
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr, pWti);
|
||||
cnfexprEval(func->expr[1], &r[1], usrptr, pWti);
|
||||
cnfexprEval(func->expr[2], &r[2], usrptr, pWti);
|
||||
str = (char*) var2CString(&r[0], &bMustFree);
|
||||
matchnbr = var2Number(&r[2], NULL);
|
||||
if(r[1].datatype == 'S') {
|
||||
@ -2118,7 +2119,7 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct svar *__restrict__ co
|
||||
ret->d.estr = es_newStrFromCStr("TABLE-NOT-FOUND", sizeof("TABLE-NOT-FOUND")-1);
|
||||
break;
|
||||
}
|
||||
cnfexprEval(func->expr[1], &r[1], usrptr);
|
||||
cnfexprEval(func->expr[1], &r[1], usrptr, pWti);
|
||||
lookup_table = ((lookup_ref_t*)func->funcdata)->self;
|
||||
if (lookup_table != NULL) {
|
||||
lookup_key_type = lookup_table->key_type;
|
||||
@ -2145,7 +2146,7 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct svar *__restrict__ co
|
||||
ret->d.n = -1;
|
||||
break;
|
||||
}
|
||||
cnfexprEval(func->expr[1], &r[1], usrptr);
|
||||
cnfexprEval(func->expr[1], &r[1], usrptr, pWti);
|
||||
str = (char*) var2CString(&r[1], &bMustFree);
|
||||
ret->d.n = dynstats_inc(func->funcdata, (uchar*)str);
|
||||
if(bMustFree) free(str);
|
||||
@ -2157,8 +2158,8 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct svar *__restrict__ co
|
||||
char result[resMax];
|
||||
char *formatstr = NULL;
|
||||
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr);
|
||||
cnfexprEval(func->expr[1], &r[1], usrptr);
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr, pWti);
|
||||
cnfexprEval(func->expr[1], &r[1], usrptr, pWti);
|
||||
|
||||
unixtime = var2Number(&r[0], &retval);
|
||||
|
||||
@ -2200,37 +2201,34 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct svar *__restrict__ co
|
||||
break;
|
||||
}
|
||||
case CNFFUNC_PARSE_TIME: {
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr);
|
||||
|
||||
cnfexprEval(func->expr[0], &r[0], usrptr, pWti);
|
||||
str = (char*) var2CString(&r[0], &bMustFree);
|
||||
|
||||
ret->datatype = 'N';
|
||||
ret->d.n = 0;
|
||||
wtiSetScriptErrno(pWti, RS_SCRIPT_EOK);
|
||||
|
||||
if (objUse(datetime, CORE_COMPONENT) == RS_RET_OK) {
|
||||
struct syslogTime s;
|
||||
int len = strlen(str);
|
||||
uchar *pszTS = (uchar*) str;
|
||||
|
||||
memset(&s, 0, sizeof(struct syslogTime));
|
||||
|
||||
// Attempt to parse the date/time string
|
||||
if (datetime.ParseTIMESTAMP3339(&s, (uchar**) &pszTS, &len) == RS_RET_OK) {
|
||||
ret->d.n = datetime.syslogTime2time_t(&s);
|
||||
DBGPRINTF("parse_time: RFC3339 format found\n");
|
||||
} else if (datetime.ParseTIMESTAMP3164(&s, (uchar**) &pszTS, &len,
|
||||
NO_PARSE3164_TZSTRING, NO_PERMIT_YEAR_AFTER_TIME) == RS_RET_OK) {
|
||||
|
||||
NO_PARSE3164_TZSTRING, NO_PERMIT_YEAR_AFTER_TIME) == RS_RET_OK) {
|
||||
time_t t = time(NULL);
|
||||
struct tm tm;
|
||||
|
||||
// Get the current UTC date
|
||||
gmtime_r(&t, &tm);
|
||||
|
||||
gmtime_r(&t, &tm); // Get the current UTC date
|
||||
// Since properly formatted RFC 3164 timestamps do not have a YEAR
|
||||
// specified, we have to assume one that seems reasonable - SW.
|
||||
s.year = estimateYear(tm.tm_year + 1900, tm.tm_mon + 1, s.month);
|
||||
|
||||
ret->d.n = datetime.syslogTime2time_t(&s);
|
||||
DBGPRINTF("parse_time: RFC3164 format found\n");
|
||||
} else {
|
||||
DBGPRINTF("parse_time: no valid format found\n");
|
||||
wtiSetScriptErrno(pWti, RS_SCRIPT_EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2238,6 +2236,11 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct svar *__restrict__ co
|
||||
varFreeMembers(&r[0]);
|
||||
break;
|
||||
}
|
||||
case CNFFUNC_SCRIPT_ERROR:
|
||||
ret->datatype = 'N';
|
||||
ret->d.n = wtiGetScriptErrno(pWti);
|
||||
DBGPRINTF("script_error() is %d\n", (int) ret->d.n);
|
||||
break;
|
||||
default:
|
||||
if(Debug) {
|
||||
char *fname = es_str2cstr(func->fname, NULL);
|
||||
@ -2338,15 +2341,15 @@ evalStrArrayCmp(es_str_t *const estr_l,
|
||||
varFreeMembers(&l)
|
||||
|
||||
#define COMP_NUM_BINOP(x) \
|
||||
cnfexprEval(expr->l, &l, usrptr); \
|
||||
cnfexprEval(expr->r, &r, usrptr); \
|
||||
cnfexprEval(expr->l, &l, usrptr, pWti); \
|
||||
cnfexprEval(expr->r, &r, usrptr, pWti); \
|
||||
ret->datatype = 'N'; \
|
||||
ret->d.n = var2Number(&l, &convok_l) x var2Number(&r, &convok_r); \
|
||||
FREE_BOTH_RET
|
||||
|
||||
#define COMP_NUM_BINOP_DIV(x) \
|
||||
cnfexprEval(expr->l, &l, usrptr); \
|
||||
cnfexprEval(expr->r, &r, usrptr); \
|
||||
cnfexprEval(expr->l, &l, usrptr, pWti); \
|
||||
cnfexprEval(expr->r, &r, usrptr, pWti); \
|
||||
ret->datatype = 'N'; \
|
||||
if((ret->d.n = var2Number(&r, &convok_r)) == 0) { \
|
||||
/* division by zero */ \
|
||||
@ -2357,13 +2360,13 @@ evalStrArrayCmp(es_str_t *const estr_l,
|
||||
|
||||
/* NOTE: array as right-hand argument MUST be handled by user */
|
||||
#define PREP_TWO_STRINGS \
|
||||
cnfexprEval(expr->l, &l, usrptr); \
|
||||
cnfexprEval(expr->l, &l, usrptr, pWti); \
|
||||
estr_l = var2String(&l, &bMustFree2); \
|
||||
if(expr->r->nodetype == 'S') { \
|
||||
estr_r = ((struct cnfstringval*)expr->r)->estr;\
|
||||
bMustFree = 0; \
|
||||
} else if(expr->r->nodetype != 'A') { \
|
||||
cnfexprEval(expr->r, &r, usrptr); \
|
||||
cnfexprEval(expr->r, &r, usrptr, pWti); \
|
||||
estr_r = var2String(&r, &bMustFree); \
|
||||
} else { \
|
||||
/* Note: this is not really necessary, but if we do not */ \
|
||||
@ -2387,9 +2390,11 @@ evalStrArrayCmp(es_str_t *const estr_l,
|
||||
* Note that we implement boolean shortcut operations. For our needs, there
|
||||
* simply is no case where full evaluation would make any sense at all.
|
||||
*/
|
||||
void
|
||||
cnfexprEval(const struct cnfexpr *__restrict__ const expr, struct svar *__restrict__ const ret,
|
||||
void *__restrict__ const usrptr)
|
||||
void ATTR_NONNULL()
|
||||
cnfexprEval(const struct cnfexpr *__restrict__ const expr,
|
||||
struct svar *__restrict__ const ret,
|
||||
void *__restrict__ const usrptr,
|
||||
wti_t *__restrict__ const pWti)
|
||||
{
|
||||
struct svar r, l; /* memory for subexpression results */
|
||||
es_str_t *__restrict__ estr_r, *__restrict__ estr_l;
|
||||
@ -2406,7 +2411,7 @@ cnfexprEval(const struct cnfexpr *__restrict__ const expr, struct svar *__restri
|
||||
/* this is optimized in regard to right param as a PoC for all compOps
|
||||
* So this is a NOT yet the copy template!
|
||||
*/
|
||||
cnfexprEval(expr->l, &l, usrptr);
|
||||
cnfexprEval(expr->l, &l, usrptr, pWti);
|
||||
ret->datatype = 'N';
|
||||
if(l.datatype == 'S') {
|
||||
if(expr->r->nodetype == 'S') {
|
||||
@ -2414,7 +2419,7 @@ cnfexprEval(const struct cnfexpr *__restrict__ const expr, struct svar *__restri
|
||||
} else if(expr->r->nodetype == 'A') {
|
||||
ret->d.n = evalStrArrayCmp(l.d.estr, (struct cnfarray*) expr->r, CMP_EQ);
|
||||
} else {
|
||||
cnfexprEval(expr->r, &r, usrptr);
|
||||
cnfexprEval(expr->r, &r, usrptr, pWti);
|
||||
if(r.datatype == 'S') {
|
||||
ret->d.n = !es_strcmp(l.d.estr, r.d.estr); /*CMP*/
|
||||
} else {
|
||||
@ -2436,7 +2441,7 @@ cnfexprEval(const struct cnfexpr *__restrict__ const expr, struct svar *__restri
|
||||
} else if(expr->r->nodetype == 'A') {
|
||||
ret->d.n = evalStrArrayCmp(estr_l, (struct cnfarray*) expr->r, CMP_EQ);
|
||||
} else {
|
||||
cnfexprEval(expr->r, &r, usrptr);
|
||||
cnfexprEval(expr->r, &r, usrptr, pWti);
|
||||
if(r.datatype == 'S') {
|
||||
ret->d.n = !es_strcmp(estr_l, r.d.estr); /*CMP*/
|
||||
} else {
|
||||
@ -2453,7 +2458,7 @@ cnfexprEval(const struct cnfexpr *__restrict__ const expr, struct svar *__restri
|
||||
}
|
||||
if(bMustFree) es_deleteStr(estr_l);
|
||||
} else {
|
||||
cnfexprEval(expr->r, &r, usrptr);
|
||||
cnfexprEval(expr->r, &r, usrptr, pWti);
|
||||
if(r.datatype == 'S') {
|
||||
n_r = var2Number(&r, &convok_r);
|
||||
if(convok_r) {
|
||||
@ -2471,8 +2476,8 @@ cnfexprEval(const struct cnfexpr *__restrict__ const expr, struct svar *__restri
|
||||
varFreeMembers(&l);
|
||||
break;
|
||||
case CMP_NE:
|
||||
cnfexprEval(expr->l, &l, usrptr);
|
||||
cnfexprEval(expr->r, &r, usrptr);
|
||||
cnfexprEval(expr->l, &l, usrptr, pWti);
|
||||
cnfexprEval(expr->r, &r, usrptr, pWti);
|
||||
ret->datatype = 'N';
|
||||
if(l.datatype == 'S') {
|
||||
if(expr->r->nodetype == 'S') {
|
||||
@ -2525,8 +2530,8 @@ cnfexprEval(const struct cnfexpr *__restrict__ const expr, struct svar *__restri
|
||||
FREE_BOTH_RET;
|
||||
break;
|
||||
case CMP_LE:
|
||||
cnfexprEval(expr->l, &l, usrptr);
|
||||
cnfexprEval(expr->r, &r, usrptr);
|
||||
cnfexprEval(expr->l, &l, usrptr, pWti);
|
||||
cnfexprEval(expr->r, &r, usrptr, pWti);
|
||||
ret->datatype = 'N';
|
||||
if(l.datatype == 'S') {
|
||||
if(r.datatype == 'S') {
|
||||
@ -2573,8 +2578,8 @@ cnfexprEval(const struct cnfexpr *__restrict__ const expr, struct svar *__restri
|
||||
FREE_BOTH_RET;
|
||||
break;
|
||||
case CMP_GE:
|
||||
cnfexprEval(expr->l, &l, usrptr);
|
||||
cnfexprEval(expr->r, &r, usrptr);
|
||||
cnfexprEval(expr->l, &l, usrptr, pWti);
|
||||
cnfexprEval(expr->r, &r, usrptr, pWti);
|
||||
ret->datatype = 'N';
|
||||
if(l.datatype == 'S') {
|
||||
if(r.datatype == 'S') {
|
||||
@ -2621,8 +2626,8 @@ cnfexprEval(const struct cnfexpr *__restrict__ const expr, struct svar *__restri
|
||||
FREE_BOTH_RET;
|
||||
break;
|
||||
case CMP_LT:
|
||||
cnfexprEval(expr->l, &l, usrptr);
|
||||
cnfexprEval(expr->r, &r, usrptr);
|
||||
cnfexprEval(expr->l, &l, usrptr, pWti);
|
||||
cnfexprEval(expr->r, &r, usrptr, pWti);
|
||||
ret->datatype = 'N';
|
||||
if(l.datatype == 'S') {
|
||||
if(r.datatype == 'S') {
|
||||
@ -2669,8 +2674,8 @@ cnfexprEval(const struct cnfexpr *__restrict__ const expr, struct svar *__restri
|
||||
FREE_BOTH_RET;
|
||||
break;
|
||||
case CMP_GT:
|
||||
cnfexprEval(expr->l, &l, usrptr);
|
||||
cnfexprEval(expr->r, &r, usrptr);
|
||||
cnfexprEval(expr->l, &l, usrptr, pWti);
|
||||
cnfexprEval(expr->r, &r, usrptr, pWti);
|
||||
ret->datatype = 'N';
|
||||
if(l.datatype == 'S') {
|
||||
if(r.datatype == 'S') {
|
||||
@ -2761,12 +2766,12 @@ cnfexprEval(const struct cnfexpr *__restrict__ const expr, struct svar *__restri
|
||||
FREE_TWO_STRINGS;
|
||||
break;
|
||||
case OR:
|
||||
cnfexprEval(expr->l, &l, usrptr);
|
||||
cnfexprEval(expr->l, &l, usrptr, pWti);
|
||||
ret->datatype = 'N';
|
||||
if(var2Number(&l, &convok_l)) {
|
||||
ret->d.n = 1ll;
|
||||
} else {
|
||||
cnfexprEval(expr->r, &r, usrptr);
|
||||
cnfexprEval(expr->r, &r, usrptr, pWti);
|
||||
if(var2Number(&r, &convok_r))
|
||||
ret->d.n = 1ll;
|
||||
else
|
||||
@ -2776,10 +2781,10 @@ cnfexprEval(const struct cnfexpr *__restrict__ const expr, struct svar *__restri
|
||||
varFreeMembers(&l);
|
||||
break;
|
||||
case AND:
|
||||
cnfexprEval(expr->l, &l, usrptr);
|
||||
cnfexprEval(expr->l, &l, usrptr, pWti);
|
||||
ret->datatype = 'N';
|
||||
if(var2Number(&l, &convok_l)) {
|
||||
cnfexprEval(expr->r, &r, usrptr);
|
||||
cnfexprEval(expr->r, &r, usrptr, pWti);
|
||||
if(var2Number(&r, &convok_r))
|
||||
ret->d.n = 1ll;
|
||||
else
|
||||
@ -2791,7 +2796,7 @@ cnfexprEval(const struct cnfexpr *__restrict__ const expr, struct svar *__restri
|
||||
varFreeMembers(&l);
|
||||
break;
|
||||
case NOT:
|
||||
cnfexprEval(expr->r, &r, usrptr);
|
||||
cnfexprEval(expr->r, &r, usrptr, pWti);
|
||||
ret->datatype = 'N';
|
||||
ret->d.n = !var2Number(&r, &convok_r);
|
||||
varFreeMembers(&r);
|
||||
@ -2842,13 +2847,13 @@ cnfexprEval(const struct cnfexpr *__restrict__ const expr, struct svar *__restri
|
||||
COMP_NUM_BINOP_DIV(%);
|
||||
break;
|
||||
case 'M':
|
||||
cnfexprEval(expr->r, &r, usrptr);
|
||||
cnfexprEval(expr->r, &r, usrptr, pWti);
|
||||
ret->datatype = 'N';
|
||||
ret->d.n = -var2Number(&r, &convok_r);
|
||||
varFreeMembers(&r);
|
||||
break;
|
||||
case 'F':
|
||||
doFuncCall((struct cnffunc*) expr, ret, usrptr);
|
||||
doFuncCall((struct cnffunc*) expr, ret, usrptr, pWti);
|
||||
break;
|
||||
default:
|
||||
ret->datatype = 'N';
|
||||
@ -2964,22 +2969,22 @@ cnfexprDestruct(struct cnfexpr *__restrict__ const expr)
|
||||
* important.
|
||||
*/
|
||||
int
|
||||
cnfexprEvalBool(struct cnfexpr *__restrict__ const expr, void *__restrict__ const usrptr)
|
||||
cnfexprEvalBool(struct cnfexpr *__restrict__ const expr, void *__restrict__ const usrptr, wti_t *const pWti)
|
||||
{
|
||||
int convok;
|
||||
struct svar ret;
|
||||
cnfexprEval(expr, &ret, usrptr);
|
||||
cnfexprEval(expr, &ret, usrptr, pWti);
|
||||
int retVal = var2Number(&ret, &convok);
|
||||
varFreeMembers(&ret);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
struct json_object*
|
||||
cnfexprEvalCollection(struct cnfexpr *__restrict__ const expr, void *__restrict__ const usrptr)
|
||||
cnfexprEvalCollection(struct cnfexpr *__restrict__ const expr, void *__restrict__ const usrptr, wti_t *const pWti)
|
||||
{
|
||||
struct svar ret;
|
||||
void *retptr;
|
||||
cnfexprEval(expr, &ret, usrptr);
|
||||
cnfexprEval(expr, &ret, usrptr, pWti);
|
||||
if(ret.datatype == 'J') {
|
||||
retptr = ret.d.json; /*caller is supposed to free the returned json-object*/
|
||||
} else {
|
||||
@ -4356,6 +4361,8 @@ funcName2ID(es_str_t *fname, unsigned short nParams)
|
||||
GENERATE_FUNC("format_time", 2, CNFFUNC_FORMAT_TIME);
|
||||
} else if(FUNC_NAME("parse_time")) {
|
||||
GENERATE_FUNC("parse_time", 1, CNFFUNC_PARSE_TIME);
|
||||
} else if(FUNC_NAME("script_error")) {
|
||||
GENERATE_FUNC("script_error", 0, CNFFUNC_SCRIPT_ERROR);
|
||||
} else {
|
||||
return CNFFUNC_INVALID;
|
||||
}
|
||||
|
||||
@ -238,7 +238,8 @@ enum cnffuncid {
|
||||
CNFFUNC_LTRIM,
|
||||
CNFFUNC_RTRIM,
|
||||
CNFFUNC_FORMAT_TIME,
|
||||
CNFFUNC_PARSE_TIME
|
||||
CNFFUNC_PARSE_TIME,
|
||||
CNFFUNC_SCRIPT_ERROR
|
||||
};
|
||||
|
||||
struct cnffunc {
|
||||
@ -295,6 +296,9 @@ struct funcData_prifilt {
|
||||
uchar pmask[LOG_NFACILITIES+1]; /* priority mask */
|
||||
};
|
||||
|
||||
/* script errno-like interface error codes: */
|
||||
#define RS_SCRIPT_EOK 0
|
||||
#define RS_SCRIPT_EINVAL 1
|
||||
|
||||
int cnfParseBuffer(char *buf, unsigned lenBuf);
|
||||
void readConfFile(FILE *fp, es_str_t **str);
|
||||
@ -313,9 +317,9 @@ void cnfobjDestruct(struct cnfobj *o);
|
||||
void cnfobjPrint(struct cnfobj *o);
|
||||
struct cnfexpr* cnfexprNew(unsigned nodetype, struct cnfexpr *l, struct cnfexpr *r);
|
||||
void cnfexprPrint(struct cnfexpr *expr, int indent);
|
||||
void cnfexprEval(const struct cnfexpr *const expr, struct svar *ret, void *pusr);
|
||||
int cnfexprEvalBool(struct cnfexpr *expr, void *usrptr);
|
||||
struct json_object* cnfexprEvalCollection(struct cnfexpr * const expr, void * const usrptr);
|
||||
void cnfexprEval(const struct cnfexpr *const expr, struct svar *ret, void *pusr, wti_t *pWti);
|
||||
int cnfexprEvalBool(struct cnfexpr *expr, void *usrptr, wti_t *pWti);
|
||||
struct json_object* cnfexprEvalCollection(struct cnfexpr * const expr, void * const usrptr, wti_t *pWti);
|
||||
void cnfexprDestruct(struct cnfexpr *expr);
|
||||
struct cnfnumval* cnfnumvalNew(long long val);
|
||||
struct cnfstringval* cnfstringvalNew(es_str_t *estr);
|
||||
|
||||
@ -218,12 +218,14 @@ finalize_it:
|
||||
RETiRet;
|
||||
}
|
||||
|
||||
static rsRetVal
|
||||
execSet(struct cnfstmt *stmt, smsg_t *pMsg)
|
||||
static rsRetVal ATTR_NONNULL()
|
||||
execSet(const struct cnfstmt *const stmt,
|
||||
smsg_t *const pMsg,
|
||||
wti_t *const __restrict__ pWti)
|
||||
{
|
||||
struct svar result;
|
||||
DEFiRet;
|
||||
cnfexprEval(stmt->d.s_set.expr, &result, pMsg);
|
||||
cnfexprEval(stmt->d.s_set.expr, &result, pMsg, pWti);
|
||||
msgSetJSONFromVar(pMsg, stmt->d.s_set.varname, &result, stmt->d.s_set.force_reset);
|
||||
varDelete(&result);
|
||||
RETiRet;
|
||||
@ -249,7 +251,7 @@ execCallIndirect(struct cnfstmt *const __restrict__ stmt,
|
||||
|
||||
assert(stmt->d.s_call_ind.expr != NULL);
|
||||
|
||||
cnfexprEval(stmt->d.s_call_ind.expr, &result, pMsg);
|
||||
cnfexprEval(stmt->d.s_call_ind.expr, &result, pMsg, pWti);
|
||||
uchar *const rsName = (uchar*) var2CString(&result, &bMustFree);
|
||||
const rsRetVal localRet = rulesetGetRuleset(loadConf, &pRuleset, rsName);
|
||||
if(localRet != RS_RET_OK) {
|
||||
@ -301,11 +303,11 @@ finalize_it:
|
||||
}
|
||||
|
||||
static rsRetVal
|
||||
execIf(struct cnfstmt *stmt, smsg_t *pMsg, wti_t *pWti)
|
||||
execIf(struct cnfstmt *const stmt, smsg_t *const pMsg, wti_t *const pWti)
|
||||
{
|
||||
sbool bRet;
|
||||
DEFiRet;
|
||||
bRet = cnfexprEvalBool(stmt->d.s_if.expr, pMsg);
|
||||
bRet = cnfexprEvalBool(stmt->d.s_if.expr, pMsg, pWti);
|
||||
DBGPRINTF("if condition result is %d\n", bRet);
|
||||
if(bRet) {
|
||||
if(stmt->d.s_if.t_then != NULL)
|
||||
@ -385,14 +387,14 @@ finalize_it:
|
||||
RETiRet;
|
||||
}
|
||||
|
||||
static rsRetVal
|
||||
execForeach(struct cnfstmt *stmt, smsg_t *pMsg, wti_t *pWti)
|
||||
static rsRetVal ATTR_NONNULL()
|
||||
execForeach(struct cnfstmt *const stmt, smsg_t *const pMsg, wti_t *const pWti)
|
||||
{
|
||||
json_object *arr = NULL;
|
||||
DEFiRet;
|
||||
|
||||
/* arr can either be an array or an associative-array (obj) */
|
||||
arr = cnfexprEvalCollection(stmt->d.s_foreach.iter->collection, pMsg);
|
||||
arr = cnfexprEvalCollection(stmt->d.s_foreach.iter->collection, pMsg, pWti);
|
||||
|
||||
if (arr == NULL) {
|
||||
DBGPRINTF("foreach loop skipped, as object to iterate upon is empty\n");
|
||||
@ -595,7 +597,7 @@ scriptExec(struct cnfstmt *const root, smsg_t *const pMsg, wti_t *const pWti)
|
||||
CHKiRet(execAct(stmt, pMsg, pWti));
|
||||
break;
|
||||
case S_SET:
|
||||
CHKiRet(execSet(stmt, pMsg));
|
||||
CHKiRet(execSet(stmt, pMsg, pWti));
|
||||
break;
|
||||
case S_UNSET:
|
||||
CHKiRet(execUnset(stmt, pMsg));
|
||||
@ -618,7 +620,7 @@ scriptExec(struct cnfstmt *const root, smsg_t *const pMsg, wti_t *const pWti)
|
||||
case S_PROPFILT:
|
||||
CHKiRet(execPROPFILT(stmt, pMsg, pWti));
|
||||
break;
|
||||
case S_RELOAD_LOOKUP_TABLE:
|
||||
case S_RELOAD_LOOKUP_TABLE:
|
||||
CHKiRet(execReloadLookupTable(stmt));
|
||||
break;
|
||||
default:
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
* (and in the web doc set on http://www.rsyslog.com/doc). Be sure to read it
|
||||
* if you are getting aquainted to the object.
|
||||
*
|
||||
* Copyright 2008-2016 Adiscon GmbH.
|
||||
* Copyright 2008-2017 Adiscon GmbH.
|
||||
*
|
||||
* This file is part of the rsyslog runtime library.
|
||||
*
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* Definition of the worker thread instance (wti) class.
|
||||
*
|
||||
* Copyright 2008-2013 Adiscon GmbH.
|
||||
* Copyright 2008-2017 Adiscon GmbH.
|
||||
*
|
||||
* This file is part of the rsyslog runtime library.
|
||||
*
|
||||
@ -78,6 +78,7 @@ struct wti_s {
|
||||
pthread_cond_t pcondBusy; /* condition to wake up the worker, protected by pmutUsr in wtp */
|
||||
DEF_ATOMIC_HELPER_MUT(mutIsRunning)
|
||||
struct {
|
||||
uint8_t script_errno; /* errno-type interface for RainerScript functions */
|
||||
uint8_t bPrevWasSuspended;
|
||||
uint8_t bDoAutoCommit; /* do a commit after each message
|
||||
* this is usually set for batches with 0 element, but may
|
||||
@ -116,12 +117,27 @@ PROTOTYPEpropSetMeth(wti, pWtp, wtp_t*);
|
||||
#define incActionNbrResRtry(pWti, pAction) ((pWti)->actWrkrInfo[(pAction)->iActionNbr].iNbrResRtry++)
|
||||
#define wtiInitIParam(piparams) (memset((piparams), 0, sizeof(actWrkrIParams_t)))
|
||||
|
||||
static inline uint8_t ATTR_UNUSED ATTR_NONNULL(1)
|
||||
wtiGetScriptErrno(const wti_t * const pWti)
|
||||
{
|
||||
assert(pWti != NULL);
|
||||
return pWti->execState.script_errno;
|
||||
}
|
||||
static inline void ATTR_UNUSED ATTR_NONNULL(1)
|
||||
wtiSetScriptErrno(wti_t * const pWti, uint8_t newval)
|
||||
{
|
||||
assert(pWti != NULL);
|
||||
pWti->execState.script_errno = newval;
|
||||
}
|
||||
|
||||
static inline void __attribute__((unused))
|
||||
wtiResetExecState(wti_t * const pWti, batch_t * const pBatch)
|
||||
{
|
||||
wtiSetScriptErrno(pWti, 0);
|
||||
pWti->execState.bPrevWasSuspended = 0;
|
||||
pWti->execState.bDoAutoCommit = (batchNumMsgs(pBatch) == 1);
|
||||
}
|
||||
|
||||
|
||||
rsRetVal wtiNewIParam(wti_t *const pWti, action_t *const pAction, actWrkrIParams_t **piparams);
|
||||
#endif /* #ifndef WTI_H_INCLUDED */
|
||||
|
||||
@ -245,6 +245,7 @@ TESTS += \
|
||||
rscript_trim.sh \
|
||||
rscript_format_time.sh \
|
||||
rscript_parse_time.sh \
|
||||
rscript_script_error.sh \
|
||||
mmanon_random_32_ipv4.sh \
|
||||
mmanon_random_cons_32_ipv4.sh \
|
||||
mmanon_recognize_ipv4.sh \
|
||||
@ -891,6 +892,7 @@ EXTRA_DIST= \
|
||||
rscript_format_time.sh \
|
||||
rscript_parse_time.sh \
|
||||
rscript_parse_time_get-ts.py \
|
||||
rscript_script_error.sh \
|
||||
mmanon_random_32_ipv4.sh \
|
||||
mmanon_random_cons_32_ipv4.sh \
|
||||
mmanon_recognize_ipv4.sh \
|
||||
|
||||
37
tests/rscript_script_error.sh
Executable file
37
tests/rscript_script_error.sh
Executable file
@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
# Added 2017-12-09 by Rainer Gerhards, released under ASL 2.0
|
||||
. $srcdir/diag.sh init
|
||||
. $srcdir/diag.sh generate-conf
|
||||
. $srcdir/diag.sh add-conf '
|
||||
module(load="../plugins/imtcp/.libs/imtcp")
|
||||
input(type="imtcp" port="13514")
|
||||
template(name="outfmt" type="string" string="%$!%\n")
|
||||
|
||||
local4.* {
|
||||
set $!valid!serial = parse_time("2017-10-05T01:10:11Z");
|
||||
set $!valid!error = script_error();
|
||||
set $!invalid!serial = parse_time("not a date/time");
|
||||
set $!invalid!error = script_error();
|
||||
set $!valid2!serial = parse_time("2017-10-05T01:10:11Z");
|
||||
set $!valid2!error = script_error();
|
||||
action(type="omfile" file="rsyslog.out.log" template="outfmt")
|
||||
}
|
||||
'
|
||||
|
||||
. $srcdir/diag.sh startup
|
||||
. $srcdir/diag.sh tcpflood -m1
|
||||
. $srcdir/diag.sh shutdown-when-empty
|
||||
. $srcdir/diag.sh wait-shutdown
|
||||
|
||||
# Our fixed and calculated expected results
|
||||
EXPECTED='{ "valid": { "serial": 1507165811, "error": 0 }, "invalid": { "serial": 0, "error": 1 }, "valid2": { "serial": 1507165811, "error": 0 } }'
|
||||
echo $EXPECTED | cmp - rsyslog.out.log
|
||||
if [[ $? -ne 0 ]]; then
|
||||
printf "Invalid function output detected!\n"
|
||||
printf "expected:\n$EXPECTED\n"
|
||||
printf "rsyslog.out is:\n"
|
||||
cat rsyslog.out.log
|
||||
. $srcdir/diag.sh error-exit 1
|
||||
fi;
|
||||
|
||||
. $srcdir/diag.sh exit
|
||||
Loading…
x
Reference in New Issue
Block a user