summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--grammar/lexer.l3
-rw-r--r--grammar/rainerscript.c252
-rw-r--r--runtime/Makefile.am20
-rw-r--r--runtime/rsconf.c3
-rw-r--r--runtime/rsyslog.c4
-rw-r--r--runtime/rule.c11
-rw-r--r--tools/syslogd.c1
7 files changed, 236 insertions, 58 deletions
diff --git a/grammar/lexer.l b/grammar/lexer.l
index d761003a..347a2a7a 100644
--- a/grammar/lexer.l
+++ b/grammar/lexer.l
@@ -72,6 +72,7 @@ struct bufstack {
YY_BUFFER_STATE bs;
int lineno;
char *fn;
+ es_str_t *estr;
} *currbs = NULL;
char *currfn; /* name of currently processed file */
@@ -228,6 +229,7 @@ cnfSetLexFile(char *fname)
bs->prev = currbs;
bs->fn = strdup(fname == NULL ? "stdin" : fname);
bs->bs = yy_scan_buffer((char*)es_getBufAddr(str), es_strlen(str));
+ bs->estr = str; /* needed so we can free it later */
currbs = bs;
currfn = bs->fn;
yylineno = 1;
@@ -253,6 +255,7 @@ popfile(void)
/* delte current entry */
yy_delete_buffer(bs->bs);
free(bs->fn);
+ free(bs->estr);
/* switch back to previous */
currbs = bs->prev;
diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c
index bcc73af0..0def9653 100644
--- a/grammar/rainerscript.c
+++ b/grammar/rainerscript.c
@@ -286,14 +286,17 @@ done:
}
/* ensure that retval is a number; if string is no number,
- * emit error message and set number to 0.
+ * try to convert it to one. The semantics from es_str2num()
+ * are used (bSuccess tells if the conversion went well or not).
*/
static inline long long
-exprret2Number(struct exprret *r)
+exprret2Number(struct exprret *r, int *bSuccess)
{
long long n;
if(r->datatype == 'S') {
- n = es_str2num(r->d.estr);
+ n = es_str2num(r->d.estr, bSuccess);
+ } else {
+ *bSuccess = 1;
}
return r->d.n;
}
@@ -316,7 +319,17 @@ exprret2String(struct exprret *r, int *bMustFree)
cnfexprEval(expr->l, &l, usrptr); \
cnfexprEval(expr->r, &r, usrptr); \
ret->datatype = 'N'; \
- ret->d.n = exprret2Number(&l) x exprret2Number(&r)
+ ret->d.n = exprret2Number(&l, &convok_l) x exprret2Number(&r, &convok_r)
+
+#define PREP_TWO_STRINGS \
+ cnfexprEval(expr->l, &l, usrptr); \
+ cnfexprEval(expr->r, &r, usrptr); \
+ estr_r = exprret2String(&r, &bMustFree); \
+ estr_l = exprret2String(&l, &bMustFree2)
+
+#define FREE_TWO_STRINGS \
+ if(bMustFree) es_deleteStr(estr_r); \
+ if(bMustFree2) es_deleteStr(estr_l)
/* evaluate an expression.
* Note that we try to avoid malloc whenever possible (because of
@@ -333,67 +346,239 @@ cnfexprEval(struct cnfexpr *expr, struct exprret *ret, void* usrptr)
{
struct exprret r, l; /* memory for subexpression results */
es_str_t *estr_r, *estr_l;
- int bMustFree;
- int bMustFree2;
+ int convok_r, convok_l;
+ int bMustFree, bMustFree2;
+ long long n_r, n_l;
//dbgprintf("eval expr %p, type '%c'(%u)\n", expr, expr->nodetype, expr->nodetype);
switch(expr->nodetype) {
+ /* note: comparison operations are extremely similar. The code can be copyied, only
+ * places flagged with "CMP" need to be changed.
+ */
case CMP_EQ:
cnfexprEval(expr->l, &l, usrptr);
cnfexprEval(expr->r, &r, usrptr);
ret->datatype = 'N';
if(l.datatype == 'S') {
if(r.datatype == 'S') {
- ret->d.n = !es_strcmp(l.d.estr, r.d.estr);
+ ret->d.n = !es_strcmp(l.d.estr, r.d.estr); /*CMP*/
} else {
- estr_r = exprret2String(&r, &bMustFree);
- ret->d.n = !es_strcmp(l.d.estr, estr_r);
- if(bMustFree) es_deleteStr(estr_r);
+ n_l = exprret2Number(&l, &convok_l);
+ if(convok_l) {
+ ret->d.n = (n_l == r.d.n); /*CMP*/
+ } else {
+ estr_r = exprret2String(&r, &bMustFree);
+ ret->d.n = !es_strcmp(l.d.estr, estr_r); /*CMP*/
+ if(bMustFree) es_deleteStr(estr_r);
+ }
}
} else {
if(r.datatype == 'S') {
- estr_l = exprret2String(&l, &bMustFree);
- ret->d.n = !es_strcmp(r.d.estr, estr_l);
- if(bMustFree) es_deleteStr(estr_l);
+ n_r = exprret2Number(&r, &convok_r);
+ if(convok_r) {
+ ret->d.n = (l.d.n == n_r); /*CMP*/
+ } else {
+ estr_l = exprret2String(&l, &bMustFree);
+ ret->d.n = !es_strcmp(r.d.estr, estr_l); /*CMP*/
+ if(bMustFree) es_deleteStr(estr_l);
+ }
} else {
- ret->d.n = (l.d.n == r.d.n);
+ ret->d.n = (l.d.n == r.d.n); /*CMP*/
}
}
break;
case CMP_NE:
- COMP_NUM_BINOP(!=);
+ cnfexprEval(expr->l, &l, usrptr);
+ cnfexprEval(expr->r, &r, usrptr);
+ ret->datatype = 'N';
+ if(l.datatype == 'S') {
+ if(r.datatype == 'S') {
+ ret->d.n = es_strcmp(l.d.estr, r.d.estr); /*CMP*/
+ } else {
+ n_l = exprret2Number(&l, &convok_l);
+ if(convok_l) {
+ ret->d.n = (n_l != r.d.n); /*CMP*/
+ } else {
+ estr_r = exprret2String(&r, &bMustFree);
+ ret->d.n = es_strcmp(l.d.estr, estr_r); /*CMP*/
+ if(bMustFree) es_deleteStr(estr_r);
+ }
+ }
+ } else {
+ if(r.datatype == 'S') {
+ n_r = exprret2Number(&r, &convok_r);
+ if(convok_r) {
+ ret->d.n = (l.d.n != n_r); /*CMP*/
+ } else {
+ estr_l = exprret2String(&l, &bMustFree);
+ ret->d.n = es_strcmp(r.d.estr, estr_l); /*CMP*/
+ if(bMustFree) es_deleteStr(estr_l);
+ }
+ } else {
+ ret->d.n = (l.d.n != r.d.n); /*CMP*/
+ }
+ }
break;
case CMP_LE:
- COMP_NUM_BINOP(<=);
+ cnfexprEval(expr->l, &l, usrptr);
+ cnfexprEval(expr->r, &r, usrptr);
+ ret->datatype = 'N';
+ if(l.datatype == 'S') {
+ if(r.datatype == 'S') {
+ ret->d.n = es_strcmp(l.d.estr, r.d.estr) <= 0; /*CMP*/
+ } else {
+ n_l = exprret2Number(&l, &convok_l);
+ if(convok_l) {
+ ret->d.n = (n_l <= r.d.n); /*CMP*/
+ } else {
+ estr_r = exprret2String(&r, &bMustFree);
+ ret->d.n = es_strcmp(l.d.estr, estr_r) <= 0; /*CMP*/
+ if(bMustFree) es_deleteStr(estr_r);
+ }
+ }
+ } else {
+ if(r.datatype == 'S') {
+ n_r = exprret2Number(&r, &convok_r);
+ if(convok_r) {
+ ret->d.n = (l.d.n <= n_r); /*CMP*/
+ } else {
+ estr_l = exprret2String(&l, &bMustFree);
+ ret->d.n = es_strcmp(r.d.estr, estr_l) <= 0; /*CMP*/
+ if(bMustFree) es_deleteStr(estr_l);
+ }
+ } else {
+ ret->d.n = (l.d.n <= r.d.n); /*CMP*/
+ }
+ }
break;
case CMP_GE:
- COMP_NUM_BINOP(>=);
+ cnfexprEval(expr->l, &l, usrptr);
+ cnfexprEval(expr->r, &r, usrptr);
+ ret->datatype = 'N';
+ if(l.datatype == 'S') {
+ if(r.datatype == 'S') {
+ ret->d.n = es_strcmp(l.d.estr, r.d.estr) >= 0; /*CMP*/
+ } else {
+ n_l = exprret2Number(&l, &convok_l);
+ if(convok_l) {
+ ret->d.n = (n_l >= r.d.n); /*CMP*/
+ } else {
+ estr_r = exprret2String(&r, &bMustFree);
+ ret->d.n = es_strcmp(l.d.estr, estr_r) >= 0; /*CMP*/
+ if(bMustFree) es_deleteStr(estr_r);
+ }
+ }
+ } else {
+ if(r.datatype == 'S') {
+ n_r = exprret2Number(&r, &convok_r);
+ if(convok_r) {
+ ret->d.n = (l.d.n >= n_r); /*CMP*/
+ } else {
+ estr_l = exprret2String(&l, &bMustFree);
+ ret->d.n = es_strcmp(r.d.estr, estr_l) >= 0; /*CMP*/
+ if(bMustFree) es_deleteStr(estr_l);
+ }
+ } else {
+ ret->d.n = (l.d.n >= r.d.n); /*CMP*/
+ }
+ }
break;
case CMP_LT:
- COMP_NUM_BINOP(<);
+ cnfexprEval(expr->l, &l, usrptr);
+ cnfexprEval(expr->r, &r, usrptr);
+ ret->datatype = 'N';
+ if(l.datatype == 'S') {
+ if(r.datatype == 'S') {
+ ret->d.n = es_strcmp(l.d.estr, r.d.estr) < 0; /*CMP*/
+ } else {
+ n_l = exprret2Number(&l, &convok_l);
+ if(convok_l) {
+ ret->d.n = (n_l < r.d.n); /*CMP*/
+ } else {
+ estr_r = exprret2String(&r, &bMustFree);
+ ret->d.n = es_strcmp(l.d.estr, estr_r) < 0; /*CMP*/
+ if(bMustFree) es_deleteStr(estr_r);
+ }
+ }
+ } else {
+ if(r.datatype == 'S') {
+ n_r = exprret2Number(&r, &convok_r);
+ if(convok_r) {
+ ret->d.n = (l.d.n < n_r); /*CMP*/
+ } else {
+ estr_l = exprret2String(&l, &bMustFree);
+ ret->d.n = es_strcmp(r.d.estr, estr_l) < 0; /*CMP*/
+ if(bMustFree) es_deleteStr(estr_l);
+ }
+ } else {
+ ret->d.n = (l.d.n < r.d.n); /*CMP*/
+ }
+ }
break;
case CMP_GT:
- COMP_NUM_BINOP(>);
- break;
- case CMP_CONTAINS:
cnfexprEval(expr->l, &l, usrptr);
cnfexprEval(expr->r, &r, usrptr);
- estr_r = exprret2String(&r, &bMustFree);
- estr_l = exprret2String(&l, &bMustFree2);
ret->datatype = 'N';
-dbgprintf("ZZZZ: contains ret %d\n", es_strContains(estr_l, estr_r));
+ if(l.datatype == 'S') {
+ if(r.datatype == 'S') {
+ ret->d.n = es_strcmp(l.d.estr, r.d.estr) > 0; /*CMP*/
+ } else {
+ n_l = exprret2Number(&l, &convok_l);
+ if(convok_l) {
+ ret->d.n = (n_l > r.d.n); /*CMP*/
+ } else {
+ estr_r = exprret2String(&r, &bMustFree);
+ ret->d.n = es_strcmp(l.d.estr, estr_r) > 0; /*CMP*/
+ if(bMustFree) es_deleteStr(estr_r);
+ }
+ }
+ } else {
+ if(r.datatype == 'S') {
+ n_r = exprret2Number(&r, &convok_r);
+ if(convok_r) {
+ ret->d.n = (l.d.n > n_r); /*CMP*/
+ } else {
+ estr_l = exprret2String(&l, &bMustFree);
+ ret->d.n = es_strcmp(r.d.estr, estr_l) > 0; /*CMP*/
+ if(bMustFree) es_deleteStr(estr_l);
+ }
+ } else {
+ ret->d.n = (l.d.n > r.d.n); /*CMP*/
+ }
+ }
+ break;
+ case CMP_STARTSWITH:
+ PREP_TWO_STRINGS;
+ ret->datatype = 'N';
+ ret->d.n = es_strncmp(estr_l, estr_r, estr_r->lenStr) == 0;
+ FREE_TWO_STRINGS;
+ break;
+ case CMP_STARTSWITHI:
+ PREP_TWO_STRINGS;
+ ret->datatype = 'N';
+ ret->d.n = es_strncasecmp(estr_l, estr_r, estr_r->lenStr) == 0;
+ FREE_TWO_STRINGS;
+ break;
+ case CMP_CONTAINS:
+ PREP_TWO_STRINGS;
+ ret->datatype = 'N';
ret->d.n = es_strContains(estr_l, estr_r) != -1;
- if(bMustFree) es_deleteStr(estr_r);
- if(bMustFree2) es_deleteStr(estr_l);
+ FREE_TWO_STRINGS;
+ break;
+ case CMP_CONTAINSI:
+ PREP_TWO_STRINGS;
+ ret->datatype = 'N';
+ ret->d.n = es_strCaseContains(estr_l, estr_r) != -1;
+ FREE_TWO_STRINGS;
break;
case OR:
cnfexprEval(expr->l, &l, usrptr);
ret->datatype = 'N';
- if(exprret2Number(&l)) {
+ if(exprret2Number(&l, &convok_l)) {
ret->d.n = 1ll;
} else {
cnfexprEval(expr->r, &r, usrptr);
- if(exprret2Number(&r))
+ if(exprret2Number(&r, &convok_r))
ret->d.n = 1ll;
else
ret->d.n = 0ll;
@@ -402,9 +587,9 @@ dbgprintf("ZZZZ: contains ret %d\n", es_strContains(estr_l, estr_r));
case AND:
cnfexprEval(expr->l, &l, usrptr);
ret->datatype = 'N';
- if(exprret2Number(&l)) {
+ if(exprret2Number(&l, &convok_l)) {
cnfexprEval(expr->r, &r, usrptr);
- if(exprret2Number(&r))
+ if(exprret2Number(&r, &convok_r))
ret->d.n = 1ll;
else
ret->d.n = 0ll;
@@ -415,7 +600,7 @@ dbgprintf("ZZZZ: contains ret %d\n", es_strContains(estr_l, estr_r));
case NOT:
cnfexprEval(expr->r, &r, usrptr);
ret->datatype = 'N';
- ret->d.n = !exprret2Number(&r);
+ ret->d.n = !exprret2Number(&r, &convok_r);
break;
case 'N':
ret->datatype = 'N';
@@ -447,7 +632,7 @@ dbgprintf("ZZZZ: contains ret %d\n", es_strContains(estr_l, estr_r));
case 'M':
cnfexprEval(expr->r, &r, usrptr);
ret->datatype = 'N';
- ret->d.n = -exprret2Number(&r);
+ ret->d.n = -exprret2Number(&r, &convok_r);
break;
default:
ret->datatype = 'N';
@@ -465,9 +650,10 @@ dbgprintf("ZZZZ: contains ret %d\n", es_strContains(estr_l, estr_r));
int
cnfexprEvalBool(struct cnfexpr *expr, void *usrptr)
{
+ int convok;
struct exprret ret;
cnfexprEval(expr, &ret, usrptr);
- return exprret2Number(&ret);
+ return exprret2Number(&ret, &convok);
}
inline static void
diff --git a/runtime/Makefile.am b/runtime/Makefile.am
index 7c3d18ef..c6c860ea 100644
--- a/runtime/Makefile.am
+++ b/runtime/Makefile.am
@@ -5,6 +5,16 @@ pkglib_LTLIBRARIES =
#pkglib_LTLIBRARIES = librsyslog.la
librsyslog_la_SOURCES = \
+ expr.c \
+ expr.h \
+ vm.c \
+ vm.h \
+ vmstk.c \
+ vmstk.h \
+ vmprg.c \
+ vmprg.h \
+ vmop.c \
+ vmop.h \
rsyslog.c \
rsyslog.h \
typedefs.h \
@@ -55,8 +65,6 @@ librsyslog_la_SOURCES = \
statsobj.h \
sync.c \
sync.h \
- expr.c \
- expr.h \
ctok.c \
ctok.h \
ctok_token.c \
@@ -71,14 +79,6 @@ librsyslog_la_SOURCES = \
wti.h \
sysvar.c \
sysvar.h \
- vm.c \
- vm.h \
- vmstk.c \
- vmstk.h \
- vmprg.c \
- vmprg.h \
- vmop.c \
- vmop.h \
queue.c \
queue.h \
ruleset.c \
diff --git a/runtime/rsconf.c b/runtime/rsconf.c
index 0d3c940a..c1bc3b72 100644
--- a/runtime/rsconf.c
+++ b/runtime/rsconf.c
@@ -1152,11 +1152,8 @@ ourConf = loadConf; // TODO: remove, once ourConf is gone!
CHKiRet(initLegacyConf());
/* open the configuration file */
- dbgprintf("ZZZZZ: calling cnfSetLexFile(%s)\n", confFile);
r = cnfSetLexFile((char*)confFile);
- dbgprintf("ZZZZZ: cnfSetLexFile returns %d, calling yyparse()\n", r);
r = yyparse();
- dbgprintf("ZZZZZ: yyparse returns %d\n", r);
//localRet = conf.processConfFile(loadConf, confFile);
CHKiRet(conf.GetNbrActActions(loadConf, &iNbrActions));
diff --git a/runtime/rsyslog.c b/runtime/rsyslog.c
index 2b8f2b64..d71fe88a 100644
--- a/runtime/rsyslog.c
+++ b/runtime/rsyslog.c
@@ -182,10 +182,13 @@ rsrtInit(char **ppErrObj, obj_if_t *pObjIF)
CHKiRet(ctok_tokenClassInit(NULL));
if(ppErrObj != NULL) *ppErrObj = "ctok";
CHKiRet(ctokClassInit(NULL));
+#if 1
if(ppErrObj != NULL) *ppErrObj = "vmstk";
CHKiRet(vmstkClassInit(NULL));
+#endif
if(ppErrObj != NULL) *ppErrObj = "sysvar";
CHKiRet(sysvarClassInit(NULL));
+#if 1
if(ppErrObj != NULL) *ppErrObj = "vm";
CHKiRet(vmClassInit(NULL));
if(ppErrObj != NULL) *ppErrObj = "vmop";
@@ -194,6 +197,7 @@ rsrtInit(char **ppErrObj, obj_if_t *pObjIF)
CHKiRet(vmprgClassInit(NULL));
if(ppErrObj != NULL) *ppErrObj = "expr";
CHKiRet(exprClassInit(NULL));
+#endif
if(ppErrObj != NULL) *ppErrObj = "rule";
CHKiRet(ruleClassInit(NULL));
if(ppErrObj != NULL) *ppErrObj = "ruleset";
diff --git a/runtime/rule.c b/runtime/rule.c
index 67ef8650..0b4b48a2 100644
--- a/runtime/rule.c
+++ b/runtime/rule.c
@@ -36,7 +36,6 @@
#include "action.h"
#include "rule.h"
#include "errmsg.h"
-#include "vm.h"
#include "var.h"
#include "srUtils.h"
#include "batch.h"
@@ -46,9 +45,7 @@
/* static data */
DEFobjStaticHelpers
DEFobjCurrIf(errmsg)
-DEFobjCurrIf(expr)
DEFobjCurrIf(var)
-DEFobjCurrIf(vm)
/* support for simple textual representation of FIOP names
@@ -124,7 +121,6 @@ shouldProcessThisMessage(rule_t *pRule, msg_t *pMsg, sbool *bProcessMsg)
uchar *pszPropVal;
int bRet = 0;
size_t propLen;
- vm_t *pVM = NULL;
var_t *pResult = NULL;
ISOBJ_TYPE_assert(pRule, rule);
@@ -276,9 +272,6 @@ shouldProcessThisMessage(rule_t *pRule, msg_t *pMsg, sbool *bProcessMsg)
finalize_it:
/* destruct in any case, not just on error, but it makes error handling much easier */
- if(pVM != NULL)
- vm.Destruct(&pVM);
-
if(pResult != NULL)
var.Destruct(&pResult);
@@ -482,9 +475,7 @@ ENDobjQueryInterface(rule)
*/
BEGINObjClassExit(rule, OBJ_IS_CORE_MODULE) /* class, version */
objRelease(errmsg, CORE_COMPONENT);
- objRelease(expr, CORE_COMPONENT);
objRelease(var, CORE_COMPONENT);
- objRelease(vm, CORE_COMPONENT);
ENDObjClassExit(rule)
@@ -495,9 +486,7 @@ ENDObjClassExit(rule)
BEGINObjClassInit(rule, 1, OBJ_IS_CORE_MODULE) /* class, version */
/* request objects we use */
CHKiRet(objUse(errmsg, CORE_COMPONENT));
- CHKiRet(objUse(expr, CORE_COMPONENT));
CHKiRet(objUse(var, CORE_COMPONENT));
- CHKiRet(objUse(vm, CORE_COMPONENT));
/* set our own handlers */
OBJSetMethodHandler(objMethod_DEBUGPRINT, ruleDebugPrint);
diff --git a/tools/syslogd.c b/tools/syslogd.c
index 79bf0c8a..f623b398 100644
--- a/tools/syslogd.c
+++ b/tools/syslogd.c
@@ -1602,7 +1602,6 @@ GlobalClassExit(void)
objRelease(ruleset, CORE_COMPONENT);
objRelease(rule, CORE_COMPONENT);
objRelease(expr, CORE_COMPONENT);
- vmClassExit(); /* this is hack, currently core_modules do not get this automatically called */
parserClassExit(); /* this is hack, currently core_modules do not get this automatically called */
rsconfClassExit(); /* this is hack, currently core_modules do not get this automatically called */
objRelease(datetime, CORE_COMPONENT);