summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2012-09-20 15:08:39 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2012-09-20 15:08:39 +0200
commit24a248d021c9d2c19b71eef26d3ddf8731e4541b (patch)
treee84c785554329456a78656998e638be0c17c6b90
parentb24af91ada128cabdfe79a3f70d5a9a508bf9f2a (diff)
downloadrsyslog-24a248d021c9d2c19b71eef26d3ddf8731e4541b.tar.gz
rsyslog-24a248d021c9d2c19b71eef26d3ddf8731e4541b.tar.bz2
rsyslog-24a248d021c9d2c19b71eef26d3ddf8731e4541b.zip
Implement RainerScript prifield() function
-rw-r--r--ChangeLog5
-rw-r--r--doc/rainerscript.html3
-rw-r--r--grammar/rainerscript.c63
-rw-r--r--grammar/rainerscript.h7
-rw-r--r--tests/Makefile.am3
-rwxr-xr-xtests/rscript_prifilt.sh13
-rw-r--r--tests/testsuites/rscript_prifilt.conf10
7 files changed, 101 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index cdf4c046..f2007e69 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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")