diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | doc/rainerscript.html | 3 | ||||
-rw-r--r-- | grammar/rainerscript.c | 63 | ||||
-rw-r--r-- | grammar/rainerscript.h | 7 | ||||
-rw-r--r-- | tests/Makefile.am | 3 | ||||
-rwxr-xr-x | tests/rscript_prifilt.sh | 13 | ||||
-rw-r--r-- | tests/testsuites/rscript_prifilt.conf | 10 |
7 files changed, 101 insertions, 3 deletions
@@ -1,6 +1,11 @@ --------------------------------------------------------------------------- Version 7.1.5 [devel] 2012-09-?? +- implemented RainerScript prifield() function - implemented RainerScript field() function +- bugfix: invalid free if function re_match() was incorrectly used + if the config file parser detected that param 2 was not constant, some + data fields were not initialized. The destructor did not care about that. + This bug happened only if rsyslog startup was unclean. --------------------------------------------------------------------------- Version 7.1.4 [devel] 2012-09-19 - implemented ability for CEE-based properties to be stored in disk queues diff --git a/doc/rainerscript.html b/doc/rainerscript.html index df31db2a..84261bdd 100644 --- a/doc/rainerscript.html +++ b/doc/rainerscript.html @@ -66,6 +66,9 @@ to search, delim is the numerical ascii value of the field delimiter (so that non-printable characters can by specified) and matchnbr is the match to search for (the first match starts at 1). This works similar as the field based property-replacer option. +<li>prifilt(constant) - mimics a traditional PRI-based filter (like "*.*" or +"mail.info"). The traditional filter string must be given as a <b>constant string</b>. +Dynamic string evaluation is not permitted (for performance reasons). </ul> <p>The following example can be used to build a dynamic filter based on some environment variable: diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c index 9eeda64e..558ec78f 100644 --- a/grammar/rainerscript.c +++ b/grammar/rainerscript.c @@ -861,6 +861,7 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr) struct var r[CNFFUNC_MAX_ARGS]; int delim; int matchnbr; + struct funcData_prifilt *pPrifilt; rsRetVal localRet; dbgprintf("rainerscript: executing function id %d\n", func->fID); @@ -952,7 +953,6 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr) delim = var2Number(&r[1], NULL); matchnbr = var2Number(&r[2], NULL); localRet = doExtractField((uchar*)str, (char) delim, matchnbr, &resStr); -dbgprintf("RRRR: field() returns %d, str: '%s'\n", localRet, resStr); if(localRet == RS_RET_OK) { ret->d.estr = es_newStrFromCStr((char*)resStr, strlen((char*)resStr)); free(resStr); @@ -969,6 +969,16 @@ dbgprintf("RRRR: field() returns %d, str: '%s'\n", localRet, resStr); if(r[1].datatype == 'S') es_deleteStr(r[1].d.estr); if(r[2].datatype == 'S') es_deleteStr(r[2].d.estr); break; + case CNFFUNC_PRIFILT: + pPrifilt = (struct funcData_prifilt*) func->funcdata; + if( (pPrifilt->pmask[((msg_t*)usrptr)->iFacility] == TABLE_NOPRI) || + ((pPrifilt->pmask[((msg_t*)usrptr)->iFacility] + & (1<<((msg_t*)usrptr)->iSeverity)) == 0) ) + ret->d.n = 0; + else + ret->d.n = 1; + ret->datatype = 'N'; + break; default: if(Debug) { fname = es_str2cstr(func->fname, NULL); @@ -1371,10 +1381,14 @@ cnffuncDestruct(struct cnffunc *func) /* some functions require special destruction */ switch(func->fID) { case CNFFUNC_RE_MATCH: - regexp.regfree(func->funcdata); + if(func->funcdata != NULL) + regexp.regfree(func->funcdata); free(func->funcdata); free(func->fname); break; + case CNFFUNC_PRIFILT: + free(func->funcdata); + break; default:break; } } @@ -1554,6 +1568,18 @@ cnfexprPrint(struct cnfexpr *expr, int indent) func = (struct cnffunc*) expr; cstrPrint("function '", func->fname); dbgprintf("' (id:%d, params:%hu)\n", func->fID, func->nParams); + if(func->fID == CNFFUNC_PRIFILT) { + struct funcData_prifilt *pD; + pD = (struct funcData_prifilt*) func->funcdata; + doIndent(indent+1); + dbgprintf("pmask: "); + for (i = 0; i <= LOG_NFACILITIES; i++) + if (pD->pmask[i] == TABLE_NOPRI) + dbgprintf(" X "); + else + dbgprintf("%2X ", pD->pmask[i]); + dbgprintf("\n"); + } for(i = 0 ; i < func->nParams ; ++i) { cnfexprPrint(func->expr[i], indent+1); } @@ -1903,6 +1929,13 @@ funcName2ID(es_str_t *fname, unsigned short nParams) return CNFFUNC_INVALID; } return CNFFUNC_FIELD; + } else if(!es_strbufcmp(fname, (unsigned char*)"prifilt", sizeof("prifilt") - 1)) { + if(nParams != 1) { + parser_errmsg("number of parameters for prifilt() must be one " + "but is %d.", nParams); + return CNFFUNC_INVALID; + } + return CNFFUNC_PRIFILT; } else { return CNFFUNC_INVALID; } @@ -1943,6 +1976,29 @@ finalize_it: RETiRet; } + +static inline rsRetVal +initFunc_prifilt(struct cnffunc *func) +{ + struct funcData_prifilt *pData; + uchar *cstr; + DEFiRet; + + func->funcdata = NULL; + if(func->expr[0]->nodetype != 'S') { + parser_errmsg("param 1 of prifilt() must be a constant string"); + FINALIZE; + } + + CHKmalloc(pData = calloc(1, sizeof(struct funcData_prifilt))); + func->funcdata = pData; + cstr = (uchar*)es_str2cstr(((struct cnfstringval*) func->expr[0])->estr, NULL); + CHKiRet(DecodePRIFilter(cstr, pData->pmask)); + free(cstr); +finalize_it: + RETiRet; +} + struct cnffunc * cnffuncNew(es_str_t *fname, struct cnffparamlst* paramlst) { @@ -1975,6 +2031,9 @@ cnffuncNew(es_str_t *fname, struct cnffparamlst* paramlst) /* need to compile the regexp in param 2, so this MUST be a constant */ initFunc_re_match(func); break; + case CNFFUNC_PRIFILT: + initFunc_prifilt(func); + break; default:break; } } diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h index a6693ef0..1b94ba21 100644 --- a/grammar/rainerscript.h +++ b/grammar/rainerscript.h @@ -208,7 +208,8 @@ enum cnffuncid { CNFFUNC_CSTR, CNFFUNC_CNUM, CNFFUNC_RE_MATCH, - CNFFUNC_FIELD + CNFFUNC_FIELD, + CNFFUNC_PRIFILT }; struct cnffunc { @@ -259,6 +260,10 @@ struct cnfparamvals { /* the values we obtained for param descr. */ unsigned char bUsed; }; +struct funcData_prifilt { + uchar pmask[LOG_NFACILITIES+1]; /* priority mask */ +}; + int cnfParseBuffer(char *buf, unsigned lenBuf); void readConfFile(FILE *fp, es_str_t **str); diff --git a/tests/Makefile.am b/tests/Makefile.am index db505a2f..4765e917 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -68,6 +68,7 @@ TESTS += \ rscript_field.sh \ rscript_stop.sh \ rscript_stop2.sh \ + rscript_prifilt.sh \ cee_simple.sh \ cee_diskqueue.sh \ linkedlistqueue.sh @@ -278,6 +279,8 @@ EXTRA_DIST= 1.rstest 2.rstest 3.rstest err1.rstest \ testsuites/rscript_stop.conf \ rscript_stop2.sh \ testsuites/rscript_stop2.conf \ + rscript_prifilt.sh \ + testsuites/rscript_prifilt.conf \ cee_simple.sh \ testsuites/cee_simple.conf \ cee_diskqueue.sh \ diff --git a/tests/rscript_prifilt.sh b/tests/rscript_prifilt.sh new file mode 100755 index 00000000..815492ab --- /dev/null +++ b/tests/rscript_prifilt.sh @@ -0,0 +1,13 @@ +# added 2012-09-20 by rgerhards +# This file is part of the rsyslog project, released under ASL 2.0 +echo =============================================================================== +echo \[rscript_prifilt.sh\]: testing rainerscript prifield\(\) function +source $srcdir/diag.sh init +source $srcdir/diag.sh startup rscript_prifilt.conf +source $srcdir/diag.sh injectmsg 0 5000 +echo doing shutdown +source $srcdir/diag.sh shutdown-when-empty +echo wait on shutdown +source $srcdir/diag.sh wait-shutdown +source $srcdir/diag.sh seq-check 0 4999 +source $srcdir/diag.sh exit diff --git a/tests/testsuites/rscript_prifilt.conf b/tests/testsuites/rscript_prifilt.conf new file mode 100644 index 00000000..8cb13a0f --- /dev/null +++ b/tests/testsuites/rscript_prifilt.conf @@ -0,0 +1,10 @@ +$IncludeConfig diag-common.conf + +template(name="outfmt" type="list") { + property(name="msg" field.delimiter="58" field.number="2") + constant(value="\n") +} + +/* tcpflood uses local4.=debug, we use a bit more generic filter */ +if prifilt("local4.*") then + action(type="omfile" file="./rsyslog.out.log" template="outfmt") |