summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--grammar/grammar.y72
-rw-r--r--grammar/lexer.l12
-rw-r--r--grammar/parserif.h2
-rw-r--r--grammar/rainerscript.c384
-rw-r--r--grammar/rainerscript.h81
-rw-r--r--runtime/Makefile.am2
-rw-r--r--runtime/conf.c115
-rw-r--r--runtime/conf.h4
-rw-r--r--runtime/rsconf.c108
-rw-r--r--runtime/rsyslog.c4
-rw-r--r--runtime/rule.c2
-rw-r--r--runtime/ruleset.c452
-rw-r--r--runtime/ruleset.h11
-rw-r--r--tools/syslogd.c5
14 files changed, 719 insertions, 535 deletions
diff --git a/grammar/grammar.y b/grammar/grammar.y
index 8371f854..65793fb1 100644
--- a/grammar/grammar.y
+++ b/grammar/grammar.y
@@ -6,10 +6,9 @@
* of course, encouraged to use new constructs only. But it needs to be noted
* that some of the legacy constructs (specifically the in-front-of-action
* PRI filter) are very hard to beat in ease of use, at least for simpler
- * cases. So while we hope that cfsysline support can be dropped some time in
- * the future, we will probably keep these useful constructs.
+ * cases.
*
- * Copyright 2011 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2011-2012 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
@@ -37,7 +36,7 @@
#define YYDEBUG 1
extern int yylineno;
-/* keep compile rule cleam of errors */
+/* keep compile rule clean of errors */
extern int yylex(void);
extern int yyerror(char*);
%}
@@ -48,11 +47,10 @@ extern int yyerror(char*);
es_str_t *estr;
enum cnfobjType objType;
struct cnfobj *obj;
+ struct cnfstmt *stmt;
struct nvlst *nvlst;
struct objlst *objlst;
- struct cnfactlst *actlst;
struct cnfexpr *expr;
- struct cnfrule *rule;
struct cnffunc *func;
struct cnffparamlst *fparams;
}
@@ -62,7 +60,6 @@ extern int yyerror(char*);
%token <estr> FUNC
%token <objType> BEGINOBJ
%token ENDOBJ
-%token <s> CFSYSLINE
%token BEGIN_ACTION
%token BEGIN_PROPERTY
%token BEGIN_CONSTANT
@@ -75,6 +72,7 @@ extern int yyerror(char*);
%token <s> BSD_HOST_SELECTOR
%token IF
%token THEN
+%token ELSE
%token OR
%token AND
%token NOT
@@ -95,13 +93,16 @@ extern int yyerror(char*);
%type <nvlst> nv nvlst
%type <obj> obj property constant
%type <objlst> propconst
-%type <actlst> actlst
+/*%type <actlst> actlst
%type <actlst> act
-%type <s> cfsysline
%type <actlst> block
+*/
%type <expr> expr
+%type <stmt> stmt s_act actlst block script
+/*
%type <rule> rule
%type <rule> scriptfilt
+*/
%type <fparams> fparams
%left AND OR
@@ -110,15 +111,9 @@ extern int yyerror(char*);
%left '*' '/' '%'
%nonassoc UMINUS NOT
-%expect 3
-/* these shift/reduce conflicts are created by the CFSYSLINE construct, which we
- * unfortunately can not avoid. The problem is that CFSYSLINE can occur both in
- * global context as well as within an action. It's not permitted somewhere else,
- * but this is suficient for conflicts. The "dangling else" built-in resolution
- * works well to solve this issue, so we accept it (it's a wonder that our
- * old style grammar doesn't work at all, so we better do not complain...).
- * Use "bison -v rscript.y" if more conflicts arise and check rscript.out for
- * were exactly these conflicts exits.
+%expect 1 /* dangling else */
+/* If more erors show up, Use "bison -v grammar.y" if more conflicts arise and
+ * check grammar.output for were exactly these conflicts exits.
*/
%%
/* note: we use left recursion below, because that saves stack space AND
@@ -127,12 +122,10 @@ extern int yyerror(char*);
*/
conf: /* empty (to end recursion) */
| conf obj { cnfDoObj($2); }
- | conf rule { cnfDoRule($2); }
- | conf cfsysline { cnfDoCfsysline($2); }
+ | conf stmt { cnfDoScript($2); }
| conf BSD_TAG_SELECTOR { cnfDoBSDTag($2); }
| conf BSD_HOST_SELECTOR { cnfDoBSDHost($2); }
obj: BEGINOBJ nvlst ENDOBJ { $$ = cnfobjNew($1, $2); }
- | BEGIN_ACTION nvlst ENDOBJ { $$ = cnfobjNew(CNFOBJ_ACTION, $2); }
| BEGIN_TPL nvlst ENDOBJ { $$ = cnfobjNew(CNFOBJ_TPL, $2); }
| BEGIN_TPL nvlst ENDOBJ '{' propconst '}'
{ $$ = cnfobjNew(CNFOBJ_TPL, $2);
@@ -143,26 +136,29 @@ propconst: { $$ = NULL; }
| propconst constant { $$ = objlstAdd($1, $2); }
property: BEGIN_PROPERTY nvlst ENDOBJ { $$ = cnfobjNew(CNFOBJ_PROPERTY, $2); }
constant: BEGIN_CONSTANT nvlst ENDOBJ { $$ = cnfobjNew(CNFOBJ_CONSTANT, $2); }
-cfsysline: CFSYSLINE { $$ = $1; }
nvlst: { $$ = NULL; }
| nvlst nv { $2->next = $1; $$ = $2; }
nv: NAME '=' VALUE { $$ = nvlstNew($1, $3); }
-rule: PRIFILT actlst { $$ = cnfruleNew(CNFFILT_PRI, $2); $$->filt.s = $1; }
- | PROPFILT actlst { $$ = cnfruleNew(CNFFILT_PROP, $2); $$->filt.s = $1; }
- | scriptfilt { $$ = $1; }
-
-scriptfilt: IF expr THEN actlst { $$ = cnfruleNew(CNFFILT_SCRIPT, $4);
- $$->filt.expr = $2; }
-block: actlst { $$ = $1; }
- | block actlst { $2->next = $1; $$ = $2; }
- /* v7: | actlst
- v7: | block rule */ /* v7 extensions require new rule engine capabilities! */
-actlst: act { $$=$1; }
- | actlst '&' act { $3->next = $1; $$ = $3; }
- | actlst cfsysline { $$ = cnfactlstAddSysline($1, $2); }
- | '{' block '}' { $$ = $2; }
-act: BEGIN_ACTION nvlst ENDOBJ { $$ = cnfactlstNew(CNFACT_V2, $2, NULL); }
- | LEGACY_ACTION { $$ = cnfactlstNew(CNFACT_LEGACY, NULL, $1); }
+script: stmt { $$ = $1; }
+ | script stmt { $$ = scriptAddStmt($1, $2); }
+stmt: actlst { $$ = $1; }
+ | STOP { $$ = cnfstmtNew(S_STOP); }
+ | IF expr THEN block { $$ = cnfstmtNew(S_IF);
+ $$->d.s_if.expr = $2;
+ $$->d.s_if.t_then = $4;
+ $$->d.s_if.t_else = NULL; }
+ | IF expr THEN block ELSE block { $$ = cnfstmtNew(S_IF);
+ $$->d.s_if.expr = $2;
+ $$->d.s_if.t_then = $4;
+ $$->d.s_if.t_else = $6; }
+ | PRIFILT block { $$ = cnfstmtNewPRIFILT($1, $2); }
+ | PROPFILT block { $$ = cnfstmtNewPROPFILT($1, $2); }
+block: stmt { $$ = $1; }
+ | '{' script '}' { $$ = $2; }
+actlst: s_act { $$ = $1; }
+ | actlst '&' s_act { $$ = scriptAddStmt($1, $3); }
+s_act: BEGIN_ACTION nvlst ENDOBJ { $$ = cnfstmtNewAct($2); }
+ | LEGACY_ACTION { $$ = cnfstmtNewLegaAct($1); }
expr: expr AND expr { $$ = cnfexprNew(AND, $1, $3); }
| expr OR expr { $$ = cnfexprNew(OR, $1, $3); }
| NOT expr { $$ = cnfexprNew(NOT, NULL, $2); }
diff --git a/grammar/lexer.l b/grammar/lexer.l
index c5e7bf7d..c52e5a01 100644
--- a/grammar/lexer.l
+++ b/grammar/lexer.l
@@ -138,6 +138,7 @@ int fileno(FILE *stream);
* to tell us the real source line.
*/
"stop" { dbgprintf("STOP\n"); return STOP; }
+"else" { dbgprintf("STOP\n"); return ELSE; }
"preprocfilelinenumber(" { BEGIN LINENO; }
<LINENO>[0-9]+ { yylineno = atoi(yytext) - 1; }
<LINENO>")" { BEGIN INITIAL; }
@@ -163,17 +164,15 @@ int fileno(FILE *stream);
BEGIN INOBJ; return BEGINOBJ; }
"action"[ \n\t]*"(" { BEGIN INOBJ; return BEGIN_ACTION; }
^[ \t]*:\$?[a-z\-]+[ ]*,[ ]*!?[a-z]+[ ]*,[ ]*\".*\" {
- yylval.s = strdup(yytext); return PROPFILT; }
-^[ \t]*[\*a-z][,\*a-z]*[0-7]*\.[,!=;\.\*a-z0-7]+ { yylval.s = strdup(yytext); return PRIFILT; }
+ yylval.s = strdup(rmLeadingSpace(yytext)); return PROPFILT; }
+^[ \t]*[\*a-z][,\*a-z]*[0-7]*\.[,!=;\.\*a-z0-7]+ { yylval.s = strdup(rmLeadingSpace(yytext)); return PRIFILT; }
"~" |
"*" |
\-\/[^*][^\n]* |
\/[^*][^\n]* |
:[a-z0-9]+:[^\n]* |
[\|\.\-\@\^?~>][^\n]+ |
-[a-z0-9_][a-z0-9_\-\+,;]* { yylval.s = strdup(yytext);
- dbgprintf("lex: LEGA ACT: '%s'\n", yytext);
- return LEGACY_ACTION; }
+[a-z0-9_][a-z0-9_\-\+,;]* { yylval.s = yytext; return LEGACY_ACTION; }
<INOBJ>")" { BEGIN INITIAL; return ENDOBJ; }
<INOBJ>[a-z][a-z0-9_\.]* { yylval.estr = es_newStrFromCStr(yytext, yyleng);
return NAME; }
@@ -193,8 +192,7 @@ int fileno(FILE *stream);
yyless(14);
BEGIN INCL;
} else {
- yylval.s = strdup(yytext);
- return CFSYSLINE;
+ cnfDoCfsysline(strdup(yytext));
}
}
![^ \t\n]+[ \t]*$ { yylval.s = strdup(yytext); return BSD_TAG_SELECTOR; }
diff --git a/grammar/parserif.h b/grammar/parserif.h
index 597cfe40..aa271ec4 100644
--- a/grammar/parserif.h
+++ b/grammar/parserif.h
@@ -15,7 +15,7 @@ extern int yylineno;
* these functions.
*/
void cnfDoObj(struct cnfobj *o);
-void cnfDoRule(struct cnfrule *rule);
+void cnfDoScript(struct cnfstmt *script);
void cnfDoCfsysline(char *ln);
void cnfDoBSDTag(char *ln);
void cnfDoBSDHost(char *ln);
diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c
index 56a6376d..30600ea3 100644
--- a/grammar/rainerscript.c
+++ b/grammar/rainerscript.c
@@ -2,7 +2,7 @@
*
* Module begun 2011-07-01 by Rainer Gerhards
*
- * Copyright 2011 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2011-2012 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
@@ -37,7 +37,9 @@
#include <libestr.h>
#include "rsyslog.h"
#include "rainerscript.h"
+#include "conf.h"
#include "parserif.h"
+#include "rsconf.h"
#include "grammar.h"
#include "queue.h"
#include "srUtils.h"
@@ -47,6 +49,37 @@
DEFobjCurrIf(obj)
DEFobjCurrIf(regexp)
+char*
+getFIOPName(unsigned iFIOP)
+{
+ char *pRet;
+ switch(iFIOP) {
+ case FIOP_CONTAINS:
+ pRet = "contains";
+ break;
+ case FIOP_ISEQUAL:
+ pRet = "isequal";
+ break;
+ case FIOP_STARTSWITH:
+ pRet = "startswith";
+ break;
+ case FIOP_REGEX:
+ pRet = "regex";
+ break;
+ case FIOP_EREREGEX:
+ pRet = "ereregex";
+ break;
+ case FIOP_ISEMPTY:
+ pRet = "isempty";
+ break;
+ default:
+ pRet = "NOP";
+ break;
+ }
+ return pRet;
+}
+
+
void
readConfFile(FILE *fp, es_str_t **str)
{
@@ -107,7 +140,6 @@ objlstNew(struct cnfobj *o)
lst->next = NULL;
lst->obj = o;
}
-dbgprintf("AAAA: creating new objlst\n");
cnfobjPrint(o);
return lst;
@@ -131,6 +163,25 @@ objlstAdd(struct objlst *root, struct cnfobj *o)
return root;
}
+/* add stmt to current script, always return root stmt pointer */
+struct cnfstmt*
+scriptAddStmt(struct cnfstmt *root, struct cnfstmt *s)
+{
+ struct cnfstmt *l;
+dbgprintf("RRRR: scriptAddStmt(%p, %p): ", root, s);
+
+ if(root == NULL) {
+ root = s;
+dbgprintf("root set to %p\n", s);
+ } else { /* find last, linear search ok, as only during config phase */
+ for(l = root ; l->next != NULL ; l = l->next)
+ ;
+ l->next = s;
+dbgprintf("%p->next = %p\n", l, s);
+ }
+ return root;
+}
+
void
objlstDestruct(struct objlst *lst)
{
@@ -661,116 +712,6 @@ cnfobjPrint(struct cnfobj *o)
}
-struct cnfactlst*
-cnfactlstNew(enum cnfactType actType, struct nvlst *lst, char *actLine)
-{
- struct cnfactlst *actlst;
-
- if((actlst = malloc(sizeof(struct cnfactlst))) != NULL) {
- actlst->next = NULL;
- actlst->syslines = NULL;
- actlst->actType = actType;
- actlst->lineno = yylineno;
- actlst->cnfFile = strdup(cnfcurrfn);
- if(actType == CNFACT_V2)
- actlst->data.lst = lst;
- else
- actlst->data.legActLine = actLine;
- }
- return actlst;
-}
-
-struct cnfactlst*
-cnfactlstAddSysline(struct cnfactlst* actlst, char *line)
-{
- struct cnfcfsyslinelst *cflst;
-
- if((cflst = malloc(sizeof(struct cnfcfsyslinelst))) != NULL) {
- cflst->line = line;
- if(actlst->syslines == NULL) {
- cflst->next = NULL;
- } else {
- cflst->next = actlst->syslines;
- }
- actlst->syslines = cflst;
- }
- return actlst;
-}
-
-
-void
-cnfactlstDestruct(struct cnfactlst *actlst)
-{
- struct cnfactlst *toDel;
-
- while(actlst != NULL) {
- toDel = actlst;
- actlst = actlst->next;
- free(toDel->cnfFile);
- cnfcfsyslinelstDestruct(toDel->syslines);
- if(toDel->actType == CNFACT_V2)
- nvlstDestruct(toDel->data.lst);
- else
- free(toDel->data.legActLine);
- free(toDel);
- }
-
-}
-
-static inline struct cnfcfsyslinelst*
-cnfcfsyslinelstReverse(struct cnfcfsyslinelst *lst)
-{
- struct cnfcfsyslinelst *curr, *prev;
- if(lst == NULL)
- return NULL;
- prev = NULL;
- while(lst != NULL) {
- curr = lst;
- lst = lst->next;
- curr->next = prev;
- prev = curr;
- }
- return prev;
-}
-
-struct cnfactlst*
-cnfactlstReverse(struct cnfactlst *actlst)
-{
- struct cnfactlst *curr, *prev;
-
- prev = NULL;
- while(actlst != NULL) {
- curr = actlst;
- actlst = actlst->next;
- curr->syslines = cnfcfsyslinelstReverse(curr->syslines);
- curr->next = prev;
- prev = curr;
- }
- return prev;
-}
-
-void
-cnfactlstPrint(struct cnfactlst *actlst)
-{
- struct cnfcfsyslinelst *cflst;
-
- while(actlst != NULL) {
- dbgprintf("aclst %p: ", actlst);
- if(actlst->actType == CNFACT_V2) {
- dbgprintf("V2 action type: ");
- nvlstPrint(actlst->data.lst);
- } else {
- dbgprintf("legacy action line: '%s'\n",
- actlst->data.legActLine);
- }
- for( cflst = actlst->syslines
- ; cflst != NULL ; cflst = cflst->next) {
- dbgprintf("action:cfsysline: '%s'\n", cflst->line);
- }
- actlst = actlst->next;
- }
-}
-
struct cnfexpr*
cnfexprNew(unsigned nodetype, struct cnfexpr *l, struct cnfexpr *r)
{
@@ -1498,6 +1439,68 @@ cnfexprPrint(struct cnfexpr *expr, int indent)
break;
}
}
+void
+cnfstmtPrint(struct cnfstmt *root, int indent)
+{
+ struct cnfstmt *stmt;
+ //dbgprintf("stmt %p, indent %d, type '%c'\n", expr, indent, expr->nodetype);
+ for(stmt = root ; stmt != NULL ; stmt = stmt->next) {
+ switch(stmt->nodetype) {
+ case S_NOP:
+ doIndent(indent); dbgprintf("NOP\n");
+ break;
+ case S_STOP:
+ doIndent(indent); dbgprintf("STOP\n");
+ break;
+ case S_ACT:
+ doIndent(indent); dbgprintf("ACTION %p (%s)\n", stmt->d.act, stmt->printable);
+ break;
+ case S_IF:
+ doIndent(indent); dbgprintf("IF\n");
+ cnfexprPrint(stmt->d.s_if.expr, indent+1);
+ doIndent(indent); dbgprintf("THEN\n");
+ cnfstmtPrint(stmt->d.s_if.t_then, indent+1);
+ if(stmt->d.s_if.t_else != NULL) {
+ doIndent(indent); dbgprintf("ELSE\n");
+ cnfstmtPrint(stmt->d.s_if.t_else, indent+1);
+ }
+ doIndent(indent); dbgprintf("END IF\n");
+ break;
+ case S_PRIFILT:
+ doIndent(indent); dbgprintf("PRIFILT '%s'\n", stmt->printable);
+ cnfstmtPrint(stmt->d.s_prifilt.t_then, indent+1);
+ doIndent(indent); dbgprintf("END PRIFILT\n");
+ break;
+ case S_PROPFILT:
+ doIndent(indent); dbgprintf("PROPFILT\n");
+ doIndent(indent); dbgprintf("\tProperty.: '%s'\n",
+ propIDToName(stmt->d.s_propfilt.propID));
+ if(stmt->d.s_propfilt.propName != NULL) {
+ char *cstr;
+ cstr = es_str2cstr(stmt->d.s_propfilt.propName, NULL);
+ doIndent(indent);
+ dbgprintf("\tCEE-Prop.: '%s'\n", cstr);
+ free(cstr);
+ }
+ doIndent(indent); dbgprintf("\tOperation: ");
+ if(stmt->d.s_propfilt.isNegated)
+ dbgprintf("NOT ");
+ dbgprintf("'%s'\n", getFIOPName(stmt->d.s_propfilt.operation));
+ if(stmt->d.s_propfilt.pCSCompValue != NULL) {
+ doIndent(indent); dbgprintf("\tValue....: '%s'\n",
+ rsCStrGetSzStrNoNULL(stmt->d.s_propfilt.pCSCompValue));
+ }
+ doIndent(indent); dbgprintf("THEN\n");
+ cnfstmtPrint(stmt->d.s_propfilt.t_then, indent+1);
+ doIndent(indent); dbgprintf("END PROPFILT\n");
+ break;
+ default:
+ dbgprintf("error: unknown stmt type %u\n",
+ (unsigned) stmt->nodetype);
+ break;
+ }
+ }
+}
struct cnfnumval*
cnfnumvalNew(long long val)
@@ -1521,6 +1524,7 @@ cnfstringvalNew(es_str_t *estr)
return strval;
}
+
struct cnfvar*
cnfvarNew(char *name)
{
@@ -1532,61 +1536,126 @@ cnfvarNew(char *name)
return var;
}
-struct cnfrule *
-cnfruleNew(enum cnfFiltType filttype, struct cnfactlst *actlst)
+struct cnfstmt *
+cnfstmtNew(unsigned s_type)
{
- struct cnfrule* cnfrule;
- if((cnfrule = malloc(sizeof(struct cnfrule))) != NULL) {
- cnfrule->nodetype = 'R';
- cnfrule->filttype = filttype;
- cnfrule->actlst = cnfactlstReverse(actlst);
+ struct cnfstmt* cnfstmt;
+ if((cnfstmt = malloc(sizeof(struct cnfstmt))) != NULL) {
+ cnfstmt->nodetype = s_type;
+ cnfstmt->printable = NULL;
+ cnfstmt->next = NULL;
}
- return cnfrule;
+ return cnfstmt;
}
void
-cnfrulePrint(struct cnfrule *rule)
+cnfstmtDestruct(struct cnfstmt *root)
{
- dbgprintf("------ start rule %p:\n", rule);
- dbgprintf("%s: ", cnfFiltType2str(rule->filttype));
- switch(rule->filttype) {
- case CNFFILT_NONE:
- break;
- case CNFFILT_PRI:
- case CNFFILT_PROP:
- dbgprintf("%s\n", rule->filt.s);
- break;
- case CNFFILT_SCRIPT:
- dbgprintf("\n");
- cnfexprPrint(rule->filt.expr, 0);
- break;
+ struct cnfstmt *stmt, *todel;
+ for(stmt = root ; stmt != NULL ; ) {
+ switch(stmt->nodetype) {
+ case S_NOP:
+ case S_STOP:
+ break;
+ case S_ACT:
+ actionDestruct(stmt->d.act);
+ break;
+ case S_IF:
+ cnfexprDestruct(stmt->d.s_if.expr);
+ if(stmt->d.s_if.t_then != NULL) {
+ cnfstmtDestruct(stmt->d.s_if.t_then);
+ }
+ if(stmt->d.s_if.t_else != NULL) {
+ cnfstmtDestruct(stmt->d.s_if.t_else);
+ }
+ break;
+ case S_PRIFILT:
+ cnfstmtDestruct(stmt->d.s_prifilt.t_then);
+ break;
+ case S_PROPFILT:
+ if(stmt->d.s_propfilt.propName != NULL)
+ es_deleteStr(stmt->d.s_propfilt.propName);
+ if(stmt->d.s_propfilt.regex_cache != NULL)
+ rsCStrRegexDestruct(&stmt->d.s_propfilt.regex_cache);
+ if(stmt->d.s_propfilt.pCSCompValue != NULL)
+ cstrDestruct(&stmt->d.s_propfilt.pCSCompValue);
+ cnfstmtDestruct(stmt->d.s_propfilt.t_then);
+ break;
+ default:
+ dbgprintf("error: unknown stmt type during destruct %u\n",
+ (unsigned) stmt->nodetype);
+ break;
+ }
+ free(stmt->printable);
+ todel = stmt;
+ stmt = stmt->next;
+ free(todel);
}
- cnfactlstPrint(rule->actlst);
- dbgprintf("------ end rule %p\n", rule);
}
-/* note: the sysline itself was already freed during processing
- * and as such MUST NOT be freed again!
- */
-void
-cnfcfsyslinelstDestruct(struct cnfcfsyslinelst *cfslst)
+struct cnfstmt *
+cnfstmtNewPRIFILT(char *prifilt, struct cnfstmt *t_then)
{
- struct cnfcfsyslinelst *toDel;
- while(cfslst != NULL) {
- toDel = cfslst;
- cfslst = cfslst->next;
- free(toDel);
+ struct cnfstmt* cnfstmt;
+ if((cnfstmt = cnfstmtNew(S_PRIFILT)) != NULL) {
+ cnfstmt->printable = (uchar*)prifilt;
+ cnfstmt->d.s_prifilt.t_then = t_then;
+ DecodePRIFilter((uchar*)prifilt, cnfstmt->d.s_prifilt.pmask);
}
+ return cnfstmt;
}
-void
-cnfruleDestruct(struct cnfrule *rule)
+struct cnfstmt *
+cnfstmtNewPROPFILT(char *propfilt, struct cnfstmt *t_then)
{
- if( rule->filttype == CNFFILT_PRI
- || rule->filttype == CNFFILT_PROP)
- free(rule->filt.s);
- cnfactlstDestruct(rule->actlst);
- free(rule);
+ struct cnfstmt* cnfstmt;
+ if((cnfstmt = cnfstmtNew(S_PROPFILT)) != NULL) {
+ cnfstmt->printable = (uchar*)propfilt;
+ cnfstmt->d.s_propfilt.t_then = t_then;
+ cnfstmt->d.s_propfilt.propName = NULL;
+ cnfstmt->d.s_propfilt.regex_cache = NULL;
+ cnfstmt->d.s_propfilt.pCSCompValue = NULL;
+ DecodePropFilter((uchar*)propfilt, cnfstmt);
+ }
+ return cnfstmt;
+}
+
+struct cnfstmt *
+cnfstmtNewAct(struct nvlst *lst)
+{
+ struct cnfstmt* cnfstmt;
+ if((cnfstmt = cnfstmtNew(S_ACT)) == NULL)
+ goto done;
+ if(actionNewInst(lst, &cnfstmt->d.act) != RS_RET_OK) {
+ // TODO:RS_RET_WARN?
+ parser_errmsg("errors occured in file '%s' around line %d",
+ cnfcurrfn, yylineno);
+ cnfstmt->nodetype = S_NOP; /* disable action! */
+ goto done;
+ }
+ cnfstmt->printable = (uchar*)strdup("action()");
+done: return cnfstmt;
+}
+
+struct cnfstmt *
+cnfstmtNewLegaAct(char *actline)
+{
+ struct cnfstmt* cnfstmt;
+ rsRetVal localRet;
+ if((cnfstmt = cnfstmtNew(S_ACT)) == NULL)
+ goto done;
+ cnfstmt->printable = (uchar*)strdup((char*)actline);
+ localRet = cflineDoAction(loadConf, (uchar**)&actline, &cnfstmt->d.act);
+ if(localRet != RS_RET_OK && localRet != RS_RET_OK_WARN) {
+ parser_errmsg("%s occured in file '%s' around line %d",
+ (localRet == RS_RET_OK_WARN) ? "warnings" : "errors",
+ cnfcurrfn, yylineno);
+ if(localRet != RS_RET_OK_WARN) {
+ cnfstmt->nodetype = S_NOP; /* disable action! */
+ goto done;
+ }
+ }
+done: return cnfstmt;
}
struct cnffparamlst *
@@ -1821,6 +1890,15 @@ cstrPrint(char *text, es_str_t *estr)
free(str);
}
+char *
+rmLeadingSpace(char *s)
+{
+ char *p;
+ for(p = s ; *p && isspace(*p) ; ++p)
+ ;
+ return(p);
+}
+
/* init must be called once before any parsing of the script files start */
rsRetVal
initRainerscript(void)
diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h
index 4c625cd8..a8d48632 100644
--- a/grammar/rainerscript.h
+++ b/grammar/rainerscript.h
@@ -3,7 +3,14 @@
#include <stdio.h>
#include <libestr.h>
#include <typedefs.h>
+#include <sys/types.h>
+#include <regex.h>
+//#include "stringbuf.h"
+/* TODO: make this hack cleaner... we have circular definitions, so we need: */
+
+
+#define LOG_NFACILITIES 24 /* current number of syslog facilities */
#define CNFFUNC_MAX_ARGS 32
/**< maximum number of arguments that any function can have (among
* others, this is used to size data structures).
@@ -91,23 +98,6 @@ struct nvlst {
*/
};
-struct cnfcfsyslinelst {
- struct cnfcfsyslinelst *next;
- char *line;
-};
-
-struct cnfactlst {
- struct cnfactlst *next;
- struct cnfcfsyslinelst *syslines;
- enum cnfactType actType;
- union {
- struct nvlst *lst;
- char *legActLine;
- } data;
- char *cnfFile;
- int lineno;
-};
-
/* the following structures support expressions, and may (very much later
* be the sole foundation for the AST.
*
@@ -118,7 +108,15 @@ struct cnfactlst {
* R - rule
* S - string
* V - var
+ * ... plus the S_* #define's below:
*/
+#define S_STOP 4000
+#define S_PRIFILT 4001
+#define S_PROPFILT 4002
+#define S_IF 4003
+#define S_ACT 4004
+#define S_NOP 4005 /* usually used to disable some statement */
+
enum cnfFiltType { CNFFILT_NONE, CNFFILT_PRI, CNFFILT_PROP, CNFFILT_SCRIPT };
static inline char*
cnfFiltType2str(enum cnfFiltType filttype)
@@ -137,14 +135,31 @@ cnfFiltType2str(enum cnfFiltType filttype)
}
-struct cnfrule {
+struct cnfstmt { /* base statement, for simple types */
unsigned nodetype;
- enum cnfFiltType filttype;
+ struct cnfstmt *next;
+ uchar *printable; /* printable text for debugging */
union {
- char *s;
- struct cnfexpr *expr;
- } filt;
- struct cnfactlst *actlst;
+ struct {
+ struct cnfexpr *expr;
+ struct cnfstmt *t_then;
+ struct cnfstmt *t_else;
+ } s_if;
+ struct {
+ uchar pmask[LOG_NFACILITIES+1]; /* priority mask */
+ struct cnfstmt *t_then;
+ } s_prifilt;
+ struct {
+ fiop_t operation;
+ regex_t *regex_cache;/* cache for compiled REs, if used */
+ struct cstr_s *pCSCompValue;/* value to "compare" against */
+ sbool isNegated;
+ uintTiny propID;/* ID of the requested property */
+ es_str_t *propName;/* name of property for CEE-based filters */
+ struct cnfstmt *t_then;
+ } s_propfilt;
+ struct action_s *act;
+ } d;
};
struct cnfexpr {
@@ -247,11 +262,6 @@ struct nvlst* nvlstFindName(struct nvlst *lst, es_str_t *name);
struct cnfobj* cnfobjNew(enum cnfobjType objType, struct nvlst *lst);
void cnfobjDestruct(struct cnfobj *o);
void cnfobjPrint(struct cnfobj *o);
-struct cnfactlst* cnfactlstNew(enum cnfactType actType, struct nvlst *lst, char *actLine);
-void cnfactlstDestruct(struct cnfactlst *actlst);
-void cnfactlstPrint(struct cnfactlst *actlst);
-struct cnfactlst* cnfactlstAddSysline(struct cnfactlst* actlst, char *line);
-struct cnfactlst* cnfactlstReverse(struct cnfactlst *actlst);
struct cnfexpr* cnfexprNew(unsigned nodetype, struct cnfexpr *l, struct cnfexpr *r);
void cnfexprPrint(struct cnfexpr *expr, int indent);
void cnfexprEval(struct cnfexpr *expr, struct var *ret, void *pusr);
@@ -259,9 +269,6 @@ int cnfexprEvalBool(struct cnfexpr *expr, void *usrptr);
void cnfexprDestruct(struct cnfexpr *expr);
struct cnfnumval* cnfnumvalNew(long long val);
struct cnfstringval* cnfstringvalNew(es_str_t *estr);
-struct cnfrule * cnfruleNew(enum cnfFiltType filttype, struct cnfactlst *actlst);
-void cnfruleDestruct(struct cnfrule *rule);
-void cnfrulePrint(struct cnfrule *rule);
struct cnfvar* cnfvarNew(char *name);
struct cnffunc * cnffuncNew(es_str_t *fname, struct cnffparamlst* paramlst);
struct cnffparamlst * cnffparamlstNew(struct cnfexpr *expr, struct cnffparamlst *next);
@@ -272,7 +279,17 @@ struct cnfparamvals* nvlstGetParams(struct nvlst *lst, struct cnfparamblk *param
void cnfparamsPrint(struct cnfparamblk *params, struct cnfparamvals *vals);
void varDelete(struct var *v);
void cnfparamvalsDestruct(struct cnfparamvals *paramvals, struct cnfparamblk *blk);
-void cnfcfsyslinelstDestruct(struct cnfcfsyslinelst *cfslst);
+struct cnfstmt * cnfstmtNew(unsigned s_type);
+void cnfstmtPrint(struct cnfstmt *stmt, int indent);
+struct cnfstmt* scriptAddStmt(struct cnfstmt *root, struct cnfstmt *s);
+struct objlst* objlstAdd(struct objlst *root, struct cnfobj *o);
+char *rmLeadingSpace(char *s);
+struct cnfstmt * cnfstmtNewPRIFILT(char *prifilt, struct cnfstmt *t_then);
+struct cnfstmt * cnfstmtNewPROPFILT(char *propfilt, struct cnfstmt *t_then);
+struct cnfstmt * cnfstmtNewAct(struct nvlst *lst);
+struct cnfstmt * cnfstmtNewLegaAct(char *actline);
+void cnfstmtDestruct(struct cnfstmt *root);
+char* getFIOPName(unsigned iFIOP);
rsRetVal initRainerscript(void);
/* debug helper */
diff --git a/runtime/Makefile.am b/runtime/Makefile.am
index 67e235a0..7af26d2b 100644
--- a/runtime/Makefile.am
+++ b/runtime/Makefile.am
@@ -63,8 +63,6 @@ librsyslog_la_SOURCES = \
queue.h \
ruleset.c \
ruleset.h \
- rule.c \
- rule.h \
prop.c \
prop.h \
cfsysline.c \
diff --git a/runtime/conf.c b/runtime/conf.c
index 488d1b86..8edf02fc 100644
--- a/runtime/conf.c
+++ b/runtime/conf.c
@@ -61,17 +61,16 @@
#include "srUtils.h"
#include "errmsg.h"
#include "net.h"
-#include "rule.h"
#include "ruleset.h"
#include "rsconf.h"
#include "unicode-helper.h"
+#include "rainerscript.h"
#ifdef OS_SOLARIS
# define NAME_MAX MAXNAMELEN
#endif
/* forward definitions */
-//static rsRetVal cfline(rsconf_t *conf, uchar *line, rule_t **pfCurr);
/* static data */
@@ -79,7 +78,6 @@ DEFobjStaticHelpers
DEFobjCurrIf(module)
DEFobjCurrIf(errmsg)
DEFobjCurrIf(net)
-DEFobjCurrIf(rule)
DEFobjCurrIf(ruleset)
int bConfStrictScoping = 0; /* force strict scoping during config processing? */
@@ -326,14 +324,9 @@ cflineParseFileName(uchar* p, uchar *pFileName, omodStringRequest_t *pOMSR, int
}
-/* Helper to cfline(). This function takes the filter part of a traditional, PRI
- * based line and decodes the PRIs given in the selector line. It processed the
- * line up to the beginning of the action part. A pointer to that beginnig is
- * passed back to the caller.
- * rgerhards 2005-09-15
- */
+/* Decode a traditional PRI filter */
/* GPLv3 - stems back to sysklogd */
-rsRetVal cflineProcessTradPRIFilter(uchar **pline, register rule_t *pRule)
+rsRetVal DecodePRIFilter(uchar *pline, uchar pmask[])
{
uchar *p;
register uchar *q;
@@ -347,22 +340,15 @@ rsRetVal cflineProcessTradPRIFilter(uchar **pline, register rule_t *pRule)
DEFiRet;
ASSERT(pline != NULL);
- ASSERT(*pline != NULL);
- ISOBJ_TYPE_assert(pRule, rule);
- dbgprintf(" - traditional PRI filter '%s'\n", *pline);
- errno = 0; /* keep strerror_r() stuff out of logerror messages */
+ dbgprintf("Decoding traditional PRI filter '%s'\n", pline);
- pRule->f_filter_type = FILTER_PRI;
- /* Note: file structure is pre-initialized to zero because it was
- * created with calloc()!
- */
for (i = 0; i <= LOG_NFACILITIES; i++) {
- pRule->f_filterData.f_pmask[i] = TABLE_NOPRI;
+ pmask[i] = TABLE_NOPRI;
}
/* scan through the list of selectors */
- for (p = *pline; *p && *p != '\t' && *p != ' ';) {
+ for (p = pline; *p && *p != '\t' && *p != ' ';) {
/* find the end of this facility name list */
for (q = p; *q && *q != '\t' && *q++ != '.'; )
continue;
@@ -411,28 +397,28 @@ rsRetVal cflineProcessTradPRIFilter(uchar **pline, register rule_t *pRule)
for (i = 0; i <= LOG_NFACILITIES; i++) {
if ( pri == INTERNAL_NOPRI ) {
if ( ignorepri )
- pRule->f_filterData.f_pmask[i] = TABLE_ALLPRI;
+ pmask[i] = TABLE_ALLPRI;
else
- pRule->f_filterData.f_pmask[i] = TABLE_NOPRI;
+ pmask[i] = TABLE_NOPRI;
}
else if ( singlpri ) {
if ( ignorepri )
- pRule->f_filterData.f_pmask[i] &= ~(1<<pri);
+ pmask[i] &= ~(1<<pri);
else
- pRule->f_filterData.f_pmask[i] |= (1<<pri);
+ pmask[i] |= (1<<pri);
} else {
if ( pri == TABLE_ALLPRI ) {
if ( ignorepri )
- pRule->f_filterData.f_pmask[i] = TABLE_NOPRI;
+ pmask[i] = TABLE_NOPRI;
else
- pRule->f_filterData.f_pmask[i] = TABLE_ALLPRI;
+ pmask[i] = TABLE_ALLPRI;
} else {
if ( ignorepri )
for (i2= 0; i2 <= pri; ++i2)
- pRule->f_filterData.f_pmask[i] &= ~(1<<i2);
+ pmask[i] &= ~(1<<i2);
else
for (i2= 0; i2 <= pri; ++i2)
- pRule->f_filterData.f_pmask[i] |= (1<<i2);
+ pmask[i] |= (1<<i2);
}
}
}
@@ -447,27 +433,27 @@ rsRetVal cflineProcessTradPRIFilter(uchar **pline, register rule_t *pRule)
if ( pri == INTERNAL_NOPRI ) {
if ( ignorepri )
- pRule->f_filterData.f_pmask[i >> 3] = TABLE_ALLPRI;
+ pmask[i >> 3] = TABLE_ALLPRI;
else
- pRule->f_filterData.f_pmask[i >> 3] = TABLE_NOPRI;
+ pmask[i >> 3] = TABLE_NOPRI;
} else if ( singlpri ) {
if ( ignorepri )
- pRule->f_filterData.f_pmask[i >> 3] &= ~(1<<pri);
+ pmask[i >> 3] &= ~(1<<pri);
else
- pRule->f_filterData.f_pmask[i >> 3] |= (1<<pri);
+ pmask[i >> 3] |= (1<<pri);
} else {
if ( pri == TABLE_ALLPRI ) {
if ( ignorepri )
- pRule->f_filterData.f_pmask[i >> 3] = TABLE_NOPRI;
+ pmask[i >> 3] = TABLE_NOPRI;
else
- pRule->f_filterData.f_pmask[i >> 3] = TABLE_ALLPRI;
+ pmask[i >> 3] = TABLE_ALLPRI;
} else {
if ( ignorepri )
for (i2= 0; i2 <= pri; ++i2)
- pRule->f_filterData.f_pmask[i >> 3] &= ~(1<<i2);
+ pmask[i >> 3] &= ~(1<<i2);
else
for (i2= 0; i2 <= pri; ++i2)
- pRule->f_filterData.f_pmask[i >> 3] |= (1<<i2);
+ pmask[i >> 3] |= (1<<i2);
}
}
}
@@ -478,11 +464,6 @@ rsRetVal cflineProcessTradPRIFilter(uchar **pline, register rule_t *pRule)
p = q;
}
- /* skip to action part */
- while (*p == '\t' || *p == ' ')
- p++;
-
- *pline = p;
RETiRet;
}
@@ -492,7 +473,7 @@ rsRetVal cflineProcessTradPRIFilter(uchar **pline, register rule_t *pRule)
* of the action part. A pointer to that beginnig is passed back to the caller.
* rgerhards 2005-09-15
*/
-rsRetVal cflineProcessPropFilter(uchar **pline, register rule_t *f)
+rsRetVal DecodePropFilter(uchar *pline, struct cnfstmt *stmt)
{
rsParsObj *pPars;
cstr_t *pCSCompOp;
@@ -501,16 +482,11 @@ rsRetVal cflineProcessPropFilter(uchar **pline, register rule_t *f)
int iOffset; /* for compare operations */
ASSERT(pline != NULL);
- ASSERT(*pline != NULL);
- ASSERT(f != NULL);
- dbgprintf(" - property-based filter '%s'\n", *pline);
- errno = 0; /* keep strerror_r() stuff out of logerror messages */
-
- f->f_filter_type = FILTER_PROP;
+ dbgprintf("Decoding property-based filter '%s'\n", pline);
/* create parser object starting with line string without leading colon */
- if((iRet = rsParsConstructFromSz(&pPars, (*pline)+1)) != RS_RET_OK) {
+ if((iRet = rsParsConstructFromSz(&pPars, pline+1)) != RS_RET_OK) {
errmsg.LogError(0, iRet, "Error %d constructing parser object - ignoring selector", iRet);
return(iRet);
}
@@ -522,15 +498,15 @@ rsRetVal cflineProcessPropFilter(uchar **pline, register rule_t *f)
rsParsDestruct(pPars);
return(iRet);
}
- iRet = propNameToID(pCSPropName, &f->f_filterData.prop.propID);
+ iRet = propNameToID(pCSPropName, &stmt->d.s_propfilt.propID);
if(iRet != RS_RET_OK) {
errmsg.LogError(0, iRet, "error %d parsing filter property - ignoring selector", iRet);
rsParsDestruct(pPars);
return(iRet);
}
- if(f->f_filterData.prop.propID == PROP_CEE) {
+ if(stmt->d.s_propfilt.propID == PROP_CEE) {
/* in CEE case, we need to preserve the actual property name */
- if((f->f_filterData.prop.propName =
+ if((stmt->d.s_propfilt.propName =
es_newStrFromBuf((char*)cstrGetSzStrNoNULL(pCSPropName)+2, cstrLen(pCSPropName)-2)) == NULL) {
cstrDestruct(&pCSPropName);
return(RS_RET_ERR);
@@ -553,38 +529,38 @@ rsRetVal cflineProcessPropFilter(uchar **pline, register rule_t *f)
*/
if(rsCStrLen(pCSCompOp) > 0) {
if(*rsCStrGetBufBeg(pCSCompOp) == '!') {
- f->f_filterData.prop.isNegated = 1;
+ stmt->d.s_propfilt.isNegated = 1;
iOffset = 1; /* ignore '!' */
} else {
- f->f_filterData.prop.isNegated = 0;
+ stmt->d.s_propfilt.isNegated = 0;
iOffset = 0;
}
} else {
- f->f_filterData.prop.isNegated = 0;
+ stmt->d.s_propfilt.isNegated = 0;
iOffset = 0;
}
if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (uchar*) "contains", 8)) {
- f->f_filterData.prop.operation = FIOP_CONTAINS;
+ stmt->d.s_propfilt.operation = FIOP_CONTAINS;
} else if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (uchar*) "isequal", 7)) {
- f->f_filterData.prop.operation = FIOP_ISEQUAL;
+ stmt->d.s_propfilt.operation = FIOP_ISEQUAL;
} else if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (uchar*) "isempty", 7)) {
- f->f_filterData.prop.operation = FIOP_ISEMPTY;
+ stmt->d.s_propfilt.operation = FIOP_ISEMPTY;
} else if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (uchar*) "startswith", 10)) {
- f->f_filterData.prop.operation = FIOP_STARTSWITH;
+ stmt->d.s_propfilt.operation = FIOP_STARTSWITH;
} else if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (unsigned char*) "regex", 5)) {
- f->f_filterData.prop.operation = FIOP_REGEX;
+ stmt->d.s_propfilt.operation = FIOP_REGEX;
} else if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (unsigned char*) "ereregex", 8)) {
- f->f_filterData.prop.operation = FIOP_EREREGEX;
+ stmt->d.s_propfilt.operation = FIOP_EREREGEX;
} else {
errmsg.LogError(0, NO_ERRCODE, "error: invalid compare operation '%s' - ignoring selector",
(char*) rsCStrGetSzStrNoNULL(pCSCompOp));
}
rsCStrDestruct(&pCSCompOp); /* no longer needed */
- if(f->f_filterData.prop.operation != FIOP_ISEMPTY) {
+ if(stmt->d.s_propfilt.operation != FIOP_ISEMPTY) {
/* read compare value */
- iRet = parsQuotedCStr(pPars, &f->f_filterData.prop.pCSCompValue);
+ iRet = parsQuotedCStr(pPars, &stmt->d.s_propfilt.pCSCompValue);
if(iRet != RS_RET_OK) {
errmsg.LogError(0, iRet, "error %d compare value property - ignoring selector", iRet);
rsParsDestruct(pPars);
@@ -592,17 +568,6 @@ rsRetVal cflineProcessPropFilter(uchar **pline, register rule_t *f)
}
}
- /* skip to action part */
- if((iRet = parsSkipWhitespace(pPars)) != RS_RET_OK) {
- errmsg.LogError(0, iRet, "error %d skipping to action part - ignoring selector", iRet);
- rsParsDestruct(pPars);
- return(iRet);
- }
-
- /* cleanup */
- *pline = *pline + rsParsGetParsePointer(pPars) + 1;
- /* we are adding one for the skipped initial ":" */
-
return rsParsDestruct(pPars);
}
@@ -831,7 +796,6 @@ CODESTARTObjClassExit(conf)
objRelease(module, CORE_COMPONENT);
objRelease(errmsg, CORE_COMPONENT);
objRelease(net, LM_NET_FILENAME);
- objRelease(rule, CORE_COMPONENT);
objRelease(ruleset, CORE_COMPONENT);
ENDObjClassExit(conf)
@@ -845,7 +809,6 @@ BEGINAbstractObjClassInit(conf, 1, OBJ_IS_CORE_MODULE) /* class, version - CHANG
CHKiRet(objUse(module, CORE_COMPONENT));
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(net, LM_NET_FILENAME)); /* TODO: make this dependcy go away! */
- CHKiRet(objUse(rule, CORE_COMPONENT));
CHKiRet(objUse(ruleset, CORE_COMPONENT));
/* These commands will NOT be supported -- the new v6.3 config system provides
diff --git a/runtime/conf.h b/runtime/conf.h
index 018d9111..04b69bc9 100644
--- a/runtime/conf.h
+++ b/runtime/conf.h
@@ -65,8 +65,8 @@ rsRetVal cflineParseFileName(uchar* p, uchar *pFileName, omodStringRequest_t *pO
/* more dirt to cover the new config interface (will go away...) */
rsRetVal cflineProcessTagSelector(uchar **pline);
rsRetVal cflineProcessHostSelector(uchar **pline);
-rsRetVal cflineProcessTradPRIFilter(uchar **pline, rule_t *pRule);
-rsRetVal cflineProcessPropFilter(uchar **pline, rule_t *f);
+rsRetVal DecodePRIFilter(uchar *pline, uchar pmask[]);
+rsRetVal DecodePropFilter(uchar *pline, struct cnfstmt *stmt);
rsRetVal cflineDoAction(rsconf_t *conf, uchar **p, action_t **ppAction);
extern EHostnameCmpMode eDfltHostnameCmpMode;
extern cstr_t *pDfltHostnameCmp;
diff --git a/runtime/rsconf.c b/runtime/rsconf.c
index 032d01a3..565bc597 100644
--- a/runtime/rsconf.c
+++ b/runtime/rsconf.c
@@ -36,7 +36,6 @@
#include "rsyslog.h"
#include "obj.h"
#include "srUtils.h"
-#include "rule.h"
#include "ruleset.h"
#include "modules.h"
#include "conf.h"
@@ -70,7 +69,6 @@
/* static data */
DEFobjStaticHelpers
-DEFobjCurrIf(rule)
DEFobjCurrIf(ruleset)
DEFobjCurrIf(module)
DEFobjCurrIf(conf)
@@ -242,54 +240,6 @@ CODESTARTobjDebugPrint(rsconf)
ENDobjDebugPrint(rsconf)
-rsRetVal
-cnfDoActlst(struct cnfactlst *actlst, rule_t *pRule)
-{
- struct cnfcfsyslinelst *cflst;
- action_t *pAction;
- uchar *str;
- rsRetVal localRet;
- DEFiRet;
-
- while(actlst != NULL) {
- dbgprintf("aclst %p: ", actlst);
- if(actlst->actType == CNFACT_V2) {
- dbgprintf("v6+ action object\n");
- if(actionNewInst(actlst->data.lst, &pAction) == RS_RET_OK) {
- iRet = llAppend(&(pRule)->llActList, NULL, (void*) pAction);
- } else {
- errmsg.LogError(0, RS_RET_ERR, "errors occured in file '%s' "
- "around line %d", actlst->cnfFile, actlst->lineno);
- }
- } else {
- DBGPRINTF("legacy action line:%s\n", actlst->data.legActLine);
- str = (uchar*) actlst->data.legActLine;
- if((localRet = cflineDoAction(loadConf, &str, &pAction)) != RS_RET_OK) {
- uchar szErrLoc[MAXFNAME + 64];
- if(localRet != RS_RET_OK_WARN) {
- DBGPRINTF("legacy action line NOT successfully processed\n");
- }
- snprintf((char*)szErrLoc, sizeof(szErrLoc) / sizeof(uchar),
- "%s, line %d", actlst->cnfFile, actlst->lineno);
- errmsg.LogError(0, NO_ERRCODE, "the last %s occured in %s:\"%s\"",
- (localRet == RS_RET_OK_WARN) ? "warning" : "error",
- (char*)szErrLoc, (char*)actlst->data.legActLine);
- if(localRet != RS_RET_OK_WARN) {
- ABORT_FINALIZE(localRet);
- }
- }
- iRet = llAppend(&(pRule)->llActList, NULL, (void*) pAction);
- }
- for( cflst = actlst->syslines
- ; cflst != NULL ; cflst = cflst->next) {
- cnfDoCfsysline(cflst->line);
- }
- actlst = actlst->next;
- }
-finalize_it:
- RETiRet;
-}
-
/* This function returns the current date in different
* variants. It is used to construct the $NOW series of
* system properties. The returned buffer must be freed
@@ -384,9 +334,6 @@ parser_errmsg(char *fmt, ...)
va_start(ap, fmt);
if(vsnprintf(errBuf, sizeof(errBuf), fmt, ap) == sizeof(errBuf))
errBuf[sizeof(errBuf)-1] = '\0';
-dbgprintf("XXXX: msg: %s\n", errBuf);
-dbgprintf("XXXX: cnfcurrfn: %s\n", cnfcurrfn);
-dbgprintf("XXXX: yylineno: %d\n", yylineno);
errmsg.LogError(0, RS_RET_CONF_PARSE_ERROR,
"error during parsing file %s, on or before line %d: %s",
cnfcurrfn, yylineno, errBuf);
@@ -429,55 +376,12 @@ void cnfDoObj(struct cnfobj *o)
cnfobjDestruct(o);
}
-void cnfDoRule(struct cnfrule *cnfrule)
+void cnfDoScript(struct cnfstmt *script)
{
- rule_t *pRule;
- uchar *str;
- rsRetVal iRet = RS_RET_OK; //DEFiRet;
-
- dbgprintf("cnf:global:rule\n");
- cnfrulePrint(cnfrule);
-
- CHKiRet(rule.Construct(&pRule)); /* create "fresh" selector */
- CHKiRet(rule.SetAssRuleset(pRule, ruleset.GetCurrent(loadConf)));
- CHKiRet(rule.ConstructFinalize(pRule));
-
- switch(cnfrule->filttype) {
- case CNFFILT_NONE:
- break;
- case CNFFILT_PRI:
- str = (uchar*) cnfrule->filt.s;
- iRet = cflineProcessTradPRIFilter(&str, pRule);
- break;
- case CNFFILT_PROP:
- dbgprintf("%s\n", cnfrule->filt.s);
- str = (uchar*) cnfrule->filt.s;
- iRet = cflineProcessPropFilter(&str, pRule);
- break;
- case CNFFILT_SCRIPT:
- pRule->f_filter_type = FILTER_EXPR;
- pRule->f_filterData.expr = cnfrule->filt.expr;
- break;
- }
- /* we now check if there are some global (BSD-style) filter conditions
- * and, if so, we copy them over. rgerhards, 2005-10-18
- */
- if(pDfltProgNameCmp != NULL) {
- CHKiRet(rsCStrConstructFromCStr(&(pRule->pCSProgNameComp), pDfltProgNameCmp));
- }
-
- if(eDfltHostnameCmpMode != HN_NO_COMP) {
- pRule->eHostnameCmpMode = eDfltHostnameCmpMode;
- CHKiRet(rsCStrConstructFromCStr(&(pRule->pCSHostnameComp), pDfltHostnameCmp));
- }
-
- cnfDoActlst(cnfrule->actlst, pRule);
-
- CHKiRet(ruleset.AddRule(rule.GetAssRuleset(pRule), &pRule));
-
-finalize_it:
- //TODO: do something with error states
- cnfruleDestruct(cnfrule);
+ // TODO: streamline this, call directly into ruleset from grammar.y
+ // TODO: BSD-Style blocks?
+ dbgprintf("cnf:global:script\n");
+ ruleset.AddScript(ruleset.GetCurrent(loadConf), script);
}
void cnfDoCfsysline(char *ln)
@@ -1377,7 +1281,6 @@ ENDobjQueryInterface(rsconf)
BEGINObjClassInit(rsconf, 1, OBJ_IS_CORE_MODULE) /* class, version */
/* request objects we use */
CHKiRet(objUse(ruleset, CORE_COMPONENT));
- CHKiRet(objUse(rule, CORE_COMPONENT));
CHKiRet(objUse(module, CORE_COMPONENT));
CHKiRet(objUse(conf, CORE_COMPONENT));
CHKiRet(objUse(errmsg, CORE_COMPONENT));
@@ -1394,7 +1297,6 @@ ENDObjClassInit(rsconf)
/* De-initialize the rsconf class.
*/
BEGINObjClassExit(rsconf, OBJ_IS_CORE_MODULE) /* class, version */
- objRelease(rule, CORE_COMPONENT);
objRelease(ruleset, CORE_COMPONENT);
objRelease(module, CORE_COMPONENT);
objRelease(conf, CORE_COMPONENT);
diff --git a/runtime/rsyslog.c b/runtime/rsyslog.c
index cbab06b7..047dfa9b 100644
--- a/runtime/rsyslog.c
+++ b/runtime/rsyslog.c
@@ -72,7 +72,6 @@
#include "glbl.h"
#include "errmsg.h"
#include "prop.h"
-#include "rule.h"
#include "ruleset.h"
#include "parser.h"
#include "strgen.h"
@@ -171,8 +170,6 @@ rsrtInit(char **ppErrObj, obj_if_t *pObjIF)
CHKiRet(glblClassInit(NULL));
if(ppErrObj != NULL) *ppErrObj = "msg";
CHKiRet(msgClassInit(NULL));
- if(ppErrObj != NULL) *ppErrObj = "rule";
- CHKiRet(ruleClassInit(NULL));
if(ppErrObj != NULL) *ppErrObj = "ruleset";
CHKiRet(rulesetClassInit(NULL));
if(ppErrObj != NULL) *ppErrObj = "wti";
@@ -220,7 +217,6 @@ rsrtExit(void)
confClassExit();
glblClassExit();
rulesetClassExit();
- ruleClassExit();
objClassExit(); /* *THIS* *MUST/SHOULD?* always be the first class initilizer being called (except debug)! */
}
diff --git a/runtime/rule.c b/runtime/rule.c
index 6d14199b..67ecd077 100644
--- a/runtime/rule.c
+++ b/runtime/rule.c
@@ -44,6 +44,7 @@ DEFobjStaticHelpers
DEFobjCurrIf(errmsg)
+#if 0
/* support for simple textual representation of FIOP names
* rgerhards, 2005-09-27
*/
@@ -76,6 +77,7 @@ getFIOPName(unsigned iFIOP)
}
return pRet;
}
+#endif
/* iterate over all actions, this is often needed, for example when HUP processing
diff --git a/runtime/ruleset.c b/runtime/ruleset.c
index 5cb34148..74f078b6 100644
--- a/runtime/ruleset.c
+++ b/runtime/ruleset.c
@@ -11,25 +11,23 @@
*
* Module begun 2009-06-10 by Rainer Gerhards
*
- * Copyright 2009-2011 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2009-2012 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
- * The rsyslog runtime library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * The rsyslog runtime library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
#include "config.h"
@@ -42,22 +40,24 @@
#include "cfsysline.h"
#include "msg.h"
#include "ruleset.h"
-#include "rule.h"
#include "errmsg.h"
#include "parser.h"
#include "batch.h"
#include "unicode-helper.h"
#include "rsconf.h"
+#include "action.h"
+#include "rainerscript.h"
+#include "srUtils.h"
#include "dirty.h" /* for main ruleset queue creation */
/* static data */
DEFobjStaticHelpers
DEFobjCurrIf(errmsg)
-DEFobjCurrIf(rule)
DEFobjCurrIf(parser)
/* forward definitions */
static rsRetVal processBatch(batch_t *pBatch);
+static rsRetVal scriptExec(struct cnfstmt *root, batch_t *pBatch, sbool *active);
/* ---------- linked-list key handling functions (ruleset) ---------- */
@@ -73,45 +73,56 @@ rulesetKeyDestruct(void __attribute__((unused)) *pData)
/* ---------- END linked-list key handling functions (ruleset) ---------- */
+/* iterate over all actions in a script (stmt subtree) */
+static void
+scriptIterateAllActions(struct cnfstmt *root, rsRetVal (*pFunc)(void*, void*), void* pParam)
+{
+ struct cnfstmt *stmt;
+ for(stmt = root ; stmt != NULL ; stmt = stmt->next) {
+ switch(stmt->nodetype) {
+ case S_NOP:
+ case S_STOP:
+ break;
+ case S_ACT:
+ DBGPRINTF("iterateAllActions calling into action %p\n", stmt->d.act);
+ pFunc(stmt->d.act, pParam);
+ break;
+ case S_IF:
+ if(stmt->d.s_if.t_then != NULL)
+ scriptIterateAllActions(stmt->d.s_if.t_then,
+ pFunc, pParam);
+ if(stmt->d.s_if.t_else != NULL)
+ scriptIterateAllActions(stmt->d.s_if.t_else,
+ pFunc, pParam);
+ break;
+ case S_PRIFILT:
+ scriptIterateAllActions(stmt->d.s_prifilt.t_then,
+ pFunc, pParam);
+ break;
+ case S_PROPFILT:
+ scriptIterateAllActions(stmt->d.s_propfilt.t_then,
+ pFunc, pParam);
+ break;
+ default:
+ dbgprintf("error: unknown stmt type %u during iterateAll\n",
+ (unsigned) stmt->nodetype);
+ break;
+ }
+ }
+}
/* driver to iterate over all of this ruleset actions */
typedef struct iterateAllActions_s {
rsRetVal (*pFunc)(void*, void*);
void *pParam;
} iterateAllActions_t;
-DEFFUNC_llExecFunc(doIterateRulesetActions)
-{
- DEFiRet;
- rule_t* pRule = (rule_t*) pData;
- iterateAllActions_t *pMyParam = (iterateAllActions_t*) pParam;
- iRet = rule.IterateAllActions(pRule, pMyParam->pFunc, pMyParam->pParam);
- RETiRet;
-}
-/* iterate over all actions of THIS rule set.
- */
-static rsRetVal
-iterateRulesetAllActions(ruleset_t *pThis, rsRetVal (*pFunc)(void*, void*), void* pParam)
-{
- iterateAllActions_t params;
- DEFiRet;
- assert(pFunc != NULL);
-
- params.pFunc = pFunc;
- params.pParam = pParam;
- CHKiRet(llExecFunc(&(pThis->llRules), doIterateRulesetActions, &params));
-
-finalize_it:
- RETiRet;
-}
-
-
/* driver to iterate over all actions */
DEFFUNC_llExecFunc(doIterateAllActions)
{
DEFiRet;
ruleset_t* pThis = (ruleset_t*) pData;
iterateAllActions_t *pMyParam = (iterateAllActions_t*) pParam;
- iRet = iterateRulesetAllActions(pThis, pMyParam->pFunc, pMyParam->pParam);
+ scriptIterateAllActions(pThis->root, pMyParam->pFunc, pMyParam->pParam);
RETiRet;
}
/* iterate over ALL actions present in the WHOLE system.
@@ -134,23 +145,6 @@ finalize_it:
}
-
-/* helper to processBatch(), used to call the configured actions. It is
- * executed from within llExecFunc() of the action list.
- * rgerhards, 2007-08-02
- */
-DEFFUNC_llExecFunc(processBatchDoRules)
-{
- rsRetVal iRet;
- ISOBJ_TYPE_assert(pData, rule);
- DBGPRINTF("Processing next rule\n");
- iRet = rule.ProcessBatch((rule_t*) pData, (batch_t*) pParam);
- DBGPRINTF("ruleset: get iRet %d from rule.ProcessMsg()\n", iRet);
- return iRet;
-}
-
-
-
/* This function is similar to processBatch(), but works on a batch that
* contains rules from multiple rulesets. In this case, we can not push
* the whole batch through the ruleset. Instead, we examine it and
@@ -207,6 +201,278 @@ finalize_it:
RETiRet;
}
+/* return a new "active" structure for the batch. Free with freeActive(). */
+static inline sbool *newActive(batch_t *pBatch)
+{
+ return malloc(sizeof(sbool) * batchNumMsgs(pBatch));
+
+}
+static inline void freeActive(sbool *active) { free(active); }
+
+/* for details, see scriptExec() header comment! */
+/* call action for all messages with filter on */
+static rsRetVal
+execAct(struct cnfstmt *stmt, batch_t *pBatch, sbool *active)
+{
+ int i;
+ DEFiRet;
+dbgprintf("RRRR: execAct: batch of %d elements, active %p\n", batchNumMsgs(pBatch), active);
+ for(i = 0 ; i < batchNumMsgs(pBatch) && !*(pBatch->pbShutdownImmediate) ; ++i) {
+ if( pBatch->pElem[i].state != BATCH_STATE_DISC
+ && (active == NULL || active[i])) {
+ DBGPRINTF("Processing next action [active=%p]\n", active);
+ stmt->d.act->submitToActQ(stmt->d.act, pBatch);
+ }
+ }
+ RETiRet;
+}
+
+/* for details, see scriptExec() header comment! */
+/* "stop" simply discards the filtered items - it's just a (hopefully more intuitive
+ * shortcut for users.
+ */
+static rsRetVal
+execStop(batch_t *pBatch, sbool *active)
+{
+ int i;
+ DEFiRet;
+ for(i = 0 ; i < batchNumMsgs(pBatch) && !*(pBatch->pbShutdownImmediate) ; ++i) {
+ if( pBatch->pElem[i].state != BATCH_STATE_DISC
+ && (active == NULL || active[i])) {
+ pBatch->pElem[i].state = BATCH_STATE_DISC;
+ }
+ }
+ RETiRet;
+}
+
+/* for details, see scriptExec() header comment! */
+// save current filter, evaluate new one
+// perform then (if any message)
+// if ELSE given:
+// set new filter, inverted
+// perform else (if any messages)
+static rsRetVal
+execIf(struct cnfstmt *stmt, batch_t *pBatch, sbool *active)
+{
+ sbool *newAct;
+ int i;
+ sbool bRet;
+ DEFiRet;
+ newAct = newActive(pBatch);
+ for(i = 0 ; i < batchNumMsgs(pBatch) && !*(pBatch->pbShutdownImmediate) ; ++i) {
+ if(pBatch->pElem[i].state == BATCH_STATE_DISC)
+ continue; /* will be ignored in any case */
+ if(active == NULL || active[i]) {
+ bRet = cnfexprEvalBool(stmt->d.s_if.expr,
+ (msg_t*)(pBatch->pElem[i].pUsrp));
+ } else
+ bRet = 0;
+ newAct[i] = bRet;
+ DBGPRINTF("batch: item %d: expr eval: %d\n", i, bRet);
+ }
+
+ if(stmt->d.s_if.t_then != NULL) {
+ scriptExec(stmt->d.s_if.t_then, pBatch, newAct);
+ }
+ if(stmt->d.s_if.t_else != NULL) {
+ for(i = 0 ; i < batchNumMsgs(pBatch) && !*(pBatch->pbShutdownImmediate)
+ ; ++i)
+ if(pBatch->pElem[i].state != BATCH_STATE_DISC)
+ newAct[i] = !newAct[i];
+ scriptExec(stmt->d.s_if.t_else, pBatch, newAct);
+ }
+ freeActive(newAct);
+ RETiRet;
+}
+
+/* for details, see scriptExec() header comment! */
+static void
+execPRIFILT(struct cnfstmt *stmt, batch_t *pBatch, sbool *active)
+{
+ sbool *thenAct;
+ msg_t *pMsg;
+ int bRet;
+ int i;
+ thenAct = newActive(pBatch);
+ for(i = 0 ; i < batchNumMsgs(pBatch) && !*(pBatch->pbShutdownImmediate) ; ++i) {
+ if(pBatch->pElem[i].state == BATCH_STATE_DISC)
+ continue; /* will be ignored in any case */
+ pMsg = (msg_t*)(pBatch->pElem[i].pUsrp);
+ if(active == NULL || active[i]) {
+ if( (stmt->d.s_prifilt.pmask[pMsg->iFacility] == TABLE_NOPRI) ||
+ ((stmt->d.s_prifilt.pmask[pMsg->iFacility]
+ & (1<<pMsg->iSeverity)) == 0) )
+ bRet = 0;
+ else
+ bRet = 1;
+ } else
+ bRet = 0;
+ thenAct[i] = bRet;
+ DBGPRINTF("batch: item %d PRIFILT %d\n", i, thenAct[i]);
+ }
+
+dbgprintf("RRRR: PRIFILT calling %p\n", stmt->d.s_prifilt.t_then);
+ scriptExec(stmt->d.s_prifilt.t_then, pBatch, thenAct);
+ freeActive(thenAct);
+}
+
+
+/* helper to execPROPFILT(), as the evaluation itself is quite lengthy */
+static int
+evalPROPFILT(struct cnfstmt *stmt, msg_t *pMsg)
+{
+ unsigned short pbMustBeFreed;
+ uchar *pszPropVal;
+ int bRet = 0;
+ size_t propLen;
+
+ pszPropVal = MsgGetProp(pMsg, NULL, stmt->d.s_propfilt.propID,
+ stmt->d.s_propfilt.propName, &propLen, &pbMustBeFreed);
+
+ /* Now do the compares (short list currently ;)) */
+ switch(stmt->d.s_propfilt.operation ) {
+ case FIOP_CONTAINS:
+ if(rsCStrLocateInSzStr(stmt->d.s_propfilt.pCSCompValue, (uchar*) pszPropVal) != -1)
+ bRet = 1;
+ break;
+ case FIOP_ISEMPTY:
+ if(propLen == 0)
+ bRet = 1; /* process message! */
+ break;
+ case FIOP_ISEQUAL:
+ if(rsCStrSzStrCmp(stmt->d.s_propfilt.pCSCompValue,
+ pszPropVal, ustrlen(pszPropVal)) == 0)
+ bRet = 1; /* process message! */
+ break;
+ case FIOP_STARTSWITH:
+ if(rsCStrSzStrStartsWithCStr(stmt->d.s_propfilt.pCSCompValue,
+ pszPropVal, ustrlen(pszPropVal)) == 0)
+ bRet = 1; /* process message! */
+ break;
+ case FIOP_REGEX:
+ if(rsCStrSzStrMatchRegex(stmt->d.s_propfilt.pCSCompValue,
+ (unsigned char*) pszPropVal, 0, &stmt->d.s_propfilt.regex_cache) == RS_RET_OK)
+ bRet = 1;
+ break;
+ case FIOP_EREREGEX:
+ if(rsCStrSzStrMatchRegex(stmt->d.s_propfilt.pCSCompValue,
+ (unsigned char*) pszPropVal, 1, &stmt->d.s_propfilt.regex_cache) == RS_RET_OK)
+ bRet = 1;
+ break;
+ default:
+ /* here, it handles NOP (for performance reasons) */
+ assert(stmt->d.s_propfilt.operation == FIOP_NOP);
+ bRet = 1; /* as good as any other default ;) */
+ break;
+ }
+
+ /* now check if the value must be negated */
+ if(stmt->d.s_propfilt.isNegated)
+ bRet = (bRet == 1) ? 0 : 1;
+
+ if(Debug) {
+ char *cstr;
+ if(stmt->d.s_propfilt.propID == PROP_CEE) {
+ cstr = es_str2cstr(stmt->d.s_propfilt.propName, NULL);
+ DBGPRINTF("Filter: check for CEE property '%s' (value '%s') ",
+ cstr, pszPropVal);
+ free(cstr);
+ } else {
+ DBGPRINTF("Filter: check for property '%s' (value '%s') ",
+ propIDToName(stmt->d.s_propfilt.propID), pszPropVal);
+ }
+ if(stmt->d.s_propfilt.isNegated)
+ DBGPRINTF("NOT ");
+ if(stmt->d.s_propfilt.operation == FIOP_ISEMPTY) {
+ DBGPRINTF("%s : %s\n",
+ getFIOPName(stmt->d.s_propfilt.operation),
+ bRet ? "TRUE" : "FALSE");
+ } else {
+ DBGPRINTF("%s '%s': %s\n",
+ getFIOPName(stmt->d.s_propfilt.operation),
+ rsCStrGetSzStrNoNULL(stmt->d.s_propfilt.pCSCompValue),
+ bRet ? "TRUE" : "FALSE");
+ }
+ }
+
+ /* cleanup */
+ if(pbMustBeFreed)
+ free(pszPropVal);
+ return bRet;
+}
+
+/* for details, see scriptExec() header comment! */
+static void
+execPROPFILT(struct cnfstmt *stmt, batch_t *pBatch, sbool *active)
+{
+ sbool *thenAct;
+ msg_t *pMsg;
+ sbool bRet;
+ int i;
+ thenAct = newActive(pBatch);
+ for(i = 0 ; i < batchNumMsgs(pBatch) && !*(pBatch->pbShutdownImmediate) ; ++i) {
+ if(pBatch->pElem[i].state == BATCH_STATE_DISC)
+ continue; /* will be ignored in any case */
+ pMsg = (msg_t*)(pBatch->pElem[i].pUsrp);
+ if(active == NULL || active[i]) {
+ bRet = evalPROPFILT(stmt, (msg_t*)(pBatch->pElem[i].pUsrp));
+ } else
+ bRet = 0;
+ thenAct[i] = bRet;
+ DBGPRINTF("batch: item %d PROPFILT %d\n", i, thenAct[i]);
+ }
+
+dbgprintf("RRRR: PROPFILT calling %p\n", stmt->d.s_propfilt.t_then);
+ scriptExec(stmt->d.s_propfilt.t_then, pBatch, thenAct);
+ freeActive(thenAct);
+}
+
+/* The rainerscript execution engine. It is debatable if that would be better
+ * contained in grammer/rainerscript.c, HOWEVER, that file focusses primarily
+ * on the parsing and object creation part. So as an actual executor, it is
+ * better suited here.
+ * param active: if NULL, all messages are active (to be processed), if non-null
+ * this is an array of the same size as the batch. If 1, the message
+ * is to be processed, otherwise not.
+ * NOTE: this function must receive batches which contain a single ruleset ONLY!
+ * rgerhards, 2012-09-04
+ */
+static rsRetVal
+scriptExec(struct cnfstmt *root, batch_t *pBatch, sbool *active)
+{
+ DEFiRet;
+ struct cnfstmt *stmt;
+
+ for(stmt = root ; stmt != NULL ; stmt = stmt->next) {
+dbgprintf("RRRR: scriptExec: batch of %d elements, active %p, stmt %p, nodetype %u\n", batchNumMsgs(pBatch), active, stmt, stmt->nodetype);
+ switch(stmt->nodetype) {
+ case S_NOP:
+ break;
+ case S_STOP:
+ execStop(pBatch, active);
+ break;
+ case S_ACT:
+ execAct(stmt, pBatch, active);
+ break;
+ case S_IF:
+ execIf(stmt, pBatch, active);
+ break;
+ case S_PRIFILT:
+ execPRIFILT(stmt, pBatch, active);
+ break;
+ case S_PROPFILT:
+ execPROPFILT(stmt, pBatch, active);
+ break;
+ default:
+ dbgprintf("error: unknown stmt type %u during exec\n",
+ (unsigned) stmt->nodetype);
+ break;
+ }
+ }
+ RETiRet;
+}
+
+
/* Process (consume) a batch of messages. Calls the actions configured.
* If the whole batch uses a singel ruleset, we can process the batch as
* a whole. Otherwise, we need to process it slower, on a message-by-message
@@ -226,7 +492,7 @@ processBatch(batch_t *pBatch)
if(pThis == NULL)
pThis = ourConf->rulesets.pDflt;
ISOBJ_TYPE_assert(pThis, ruleset);
- CHKiRet(llExecFunc(&pThis->llRules, processBatchDoRules, pBatch));
+ CHKiRet(scriptExec(pThis->root, pBatch, NULL));
} else {
CHKiRet(processBatchMultiRuleset(pBatch));
}
@@ -248,29 +514,18 @@ GetParserList(rsconf_t *conf, msg_t *pMsg)
}
-/* Add a new rule to the end of the current rule set. We do a number
- * of checks and ignore the rule if it does not pass them.
- */
-static rsRetVal
-addRule(ruleset_t *pThis, rule_t **ppRule)
+/* Add a script block to the current ruleset */
+static void
+addScript(ruleset_t *pThis, struct cnfstmt *script)
{
- int iActionCnt;
- DEFiRet;
-
- ISOBJ_TYPE_assert(pThis, ruleset);
- ISOBJ_TYPE_assert(*ppRule, rule);
-
- CHKiRet(llGetNumElts(&(*ppRule)->llActList, &iActionCnt));
- if(iActionCnt == 0) {
- errmsg.LogError(0, NO_ERRCODE, "warning: selector line without actions will be discarded");
- rule.Destruct(ppRule);
- } else {
- CHKiRet(llAppend(&pThis->llRules, NULL, *ppRule));
- DBGPRINTF("selector line successfully processed, %d actions\n", iActionCnt);
+ if(pThis->last == NULL)
+ pThis->root = pThis->last = script;
+ else {
+ pThis->last->next = script;
+ pThis->last = script;
}
-
-finalize_it:
- RETiRet;
+dbgprintf("RRRR: ruleset added script, script total now is:\n");
+ cnfstmtPrint(pThis->root, 0);
}
@@ -362,23 +617,11 @@ finalize_it:
}
-/* destructor we need to destruct rules inside our linked list contents.
- */
-static rsRetVal
-doRuleDestruct(void *pData)
-{
- rule_t *pRule = (rule_t *) pData;
- DEFiRet;
- rule.Destruct(&pRule);
- RETiRet;
-}
-
-
/* Standard-Constructor
*/
BEGINobjConstruct(ruleset) /* be sure to specify the object type also in END macro! */
- CHKiRet(llInit(&pThis->llRules, doRuleDestruct, NULL, NULL));
-finalize_it:
+ pThis->root = NULL;
+ pThis->last = NULL;
ENDobjConstruct(ruleset)
@@ -421,8 +664,8 @@ CODESTARTobjDestruct(ruleset)
if(pThis->pParserLst != NULL) {
parser.DestructParserList(&pThis->pParserLst);
}
- llDestroy(&pThis->llRules);
free(pThis->pszName);
+ cnfstmtDestruct(pThis->root);
ENDobjDestruct(ruleset)
@@ -456,16 +699,11 @@ rulesetDestructForLinkedList(void *pData)
return rulesetDestruct(&pThis);
}
-/* helper for debugPrint(), initiates rule printing */
-DEFFUNC_llExecFunc(doDebugPrintRule)
-{
- return rule.DebugPrint((rule_t*) pData);
-}
/* debugprint for the ruleset object */
BEGINobjDebugPrint(ruleset) /* be sure to specify the object type also in END and CODESTART macros! */
CODESTARTobjDebugPrint(ruleset)
dbgoprint((obj_t*) pThis, "rsyslog ruleset %s:\n", pThis->pszName);
- llExecFunc(&pThis->llRules, doDebugPrintRule, NULL);
+ cnfstmtPrint(pThis->root, 0);
ENDobjDebugPrint(ruleset)
@@ -595,7 +833,7 @@ CODESTARTobjQueryInterface(ruleset)
pIf->IterateAllActions = iterateAllActions;
pIf->DestructAllActions = destructAllActions;
- pIf->AddRule = addRule;
+ pIf->AddScript = addScript;
pIf->ProcessBatch = processBatch;
pIf->SetName = setName;
pIf->DebugPrintAll = debugPrintAll;
@@ -614,7 +852,6 @@ ENDobjQueryInterface(ruleset)
*/
BEGINObjClassExit(ruleset, OBJ_IS_CORE_MODULE) /* class, version */
objRelease(errmsg, CORE_COMPONENT);
- objRelease(rule, CORE_COMPONENT);
objRelease(parser, CORE_COMPONENT);
ENDObjClassExit(ruleset)
@@ -626,7 +863,6 @@ ENDObjClassExit(ruleset)
BEGINObjClassInit(ruleset, 1, OBJ_IS_CORE_MODULE) /* class, version */
/* request objects we use */
CHKiRet(objUse(errmsg, CORE_COMPONENT));
- CHKiRet(objUse(rule, CORE_COMPONENT));
/* set our own handlers */
OBJSetMethodHandler(objMethod_DEBUGPRINT, rulesetDebugPrint);
diff --git a/runtime/ruleset.h b/runtime/ruleset.h
index f4443e18..50c8071e 100644
--- a/runtime/ruleset.h
+++ b/runtime/ruleset.h
@@ -29,9 +29,10 @@
/* the ruleset object */
struct ruleset_s {
BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
- linkedList_t llRules; /* this is NOT a pointer - no typo here ;) */
uchar *pszName; /* name of our ruleset */
qqueue_t *pQueue; /* "main" message queue, if the ruleset has its own (else NULL) */
+ struct cnfstmt *root;
+ struct cnfstmt *last;
parserList_t *pParserLst;/* list of parsers to use for this ruleset */
};
@@ -42,9 +43,7 @@ BEGINinterface(ruleset) /* name must also be changed in ENDinterface macro! */
rsRetVal (*Construct)(ruleset_t **ppThis);
rsRetVal (*ConstructFinalize)(rsconf_t *conf, ruleset_t __attribute__((unused)) *pThis);
rsRetVal (*Destruct)(ruleset_t **ppThis);
- rsRetVal (*IterateAllActions)(rsconf_t *conf, rsRetVal (*pFunc)(void*, void*), void* pParam);
rsRetVal (*DestructAllActions)(rsconf_t *conf);
- rsRetVal (*AddRule)(ruleset_t *pThis, rule_t **ppRule);
rsRetVal (*SetName)(ruleset_t *pThis, uchar *pszName);
rsRetVal (*ProcessBatch)(batch_t*);
rsRetVal (*GetRuleset)(rsconf_t *conf, ruleset_t **ppThis, uchar*);
@@ -60,8 +59,12 @@ BEGINinterface(ruleset) /* name must also be changed in ENDinterface macro! */
* removed conf ptr from SetName, AddRule as the flex/bison based
* system uses globals in any case.
*/
+ /* v7, 2012-09-04 */
+ /* AddRule() removed */
+ /*TODO:REMOVE*/rsRetVal (*IterateAllActions)(rsconf_t *conf, rsRetVal (*pFunc)(void*, void*), void* pParam);
+ void (*AddScript)(ruleset_t *pThis, struct cnfstmt *script);
ENDinterface(ruleset)
-#define rulesetCURR_IF_VERSION 6 /* increment whenever you change the interface structure! */
+#define rulesetCURR_IF_VERSION 7 /* increment whenever you change the interface structure! */
/* prototypes */
diff --git a/tools/syslogd.c b/tools/syslogd.c
index 219b41ab..a30fb464 100644
--- a/tools/syslogd.c
+++ b/tools/syslogd.c
@@ -119,7 +119,6 @@
#include "batch.h"
#include "unicode-helper.h"
#include "ruleset.h"
-#include "rule.h"
#include "net.h"
#include "prop.h"
#include "rsconf.h"
@@ -134,7 +133,6 @@ DEFobjCurrIf(datetime) /* TODO: make go away! */
DEFobjCurrIf(conf)
DEFobjCurrIf(module)
DEFobjCurrIf(errmsg)
-DEFobjCurrIf(rule)
DEFobjCurrIf(ruleset)
DEFobjCurrIf(prop)
DEFobjCurrIf(parser)
@@ -1453,8 +1451,6 @@ InitGlobalClasses(void)
CHKiRet(objUse(module, CORE_COMPONENT));
pErrObj = "datetime";
CHKiRet(objUse(datetime, CORE_COMPONENT));
- pErrObj = "rule";
- CHKiRet(objUse(rule, CORE_COMPONENT));
pErrObj = "ruleset";
CHKiRet(objUse(ruleset, CORE_COMPONENT));
pErrObj = "conf";
@@ -1508,7 +1504,6 @@ GlobalClassExit(void)
objRelease(prop, CORE_COMPONENT);
objRelease(conf, CORE_COMPONENT);
objRelease(ruleset, CORE_COMPONENT);
- objRelease(rule, CORE_COMPONENT);
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);