From 07527fbd38dbed4ed1708fe558ad34b1ebf9e48c Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 3 Sep 2012 15:53:31 +0200 Subject: new ruleengine: first shot at grammar --- grammar/grammar.y | 34 ++++++++++++++++++++++------------ grammar/lexer.l | 8 +++++--- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/grammar/grammar.y b/grammar/grammar.y index 8371f854..ac0be30b 100644 --- a/grammar/grammar.y +++ b/grammar/grammar.y @@ -95,13 +95,15 @@ extern int yyerror(char*); %type nv nvlst %type obj property constant %type propconst -%type actlst +/*%type actlst %type act -%type cfsysline %type block +*/ %type expr +/* %type rule %type scriptfilt +*/ %type fparams %left AND OR @@ -110,14 +112,14 @@ extern int yyerror(char*); %left '*' '/' '%' %nonassoc UMINUS NOT -%expect 3 +/*%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 + * Use "bison -v grammar.y" if more conflicts arise and check grammar.output for * were exactly these conflicts exits. */ %% @@ -127,12 +129,10 @@ extern int yyerror(char*); */ conf: /* empty (to end recursion) */ | conf obj { cnfDoObj($2); } - | conf rule { cnfDoRule($2); } - | conf cfsysline { cnfDoCfsysline($2); } + | conf stmt { dbgprintf("RRRR: top-level stmt"); } | 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,10 +143,19 @@ 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); } +script: stmt { dbgprintf("RRRR: root stmt\n"); } + | script stmt { dbgprintf("RRRR: stmt in list\n"); } +stmt: s_act { dbgprintf("RRRR: have s_act\n"); } + | STOP { dbgprintf("RRRR: have STOP\n"); } + | IF expr THEN block { dbgprintf("RRRR: have s_if \n"); } + | PRIFILT block { dbgprintf("RRRR: have s_prifilt\n"); } + | PROPFILT block { dbgprintf("RRRR: have s_propfilt\n"); } +block: stmt { dbgprintf("RRRR: have block:stmt\n"); } + | '{' script '}' { dbgprintf("RRRR: have block:script\n"); } +/* rule: PRIFILT actlst { $$ = cnfruleNew(CNFFILT_PRI, $2); $$->filt.s = $1; } | PROPFILT actlst { $$ = cnfruleNew(CNFFILT_PROP, $2); $$->filt.s = $1; } | scriptfilt { $$ = $1; } @@ -155,14 +164,15 @@ 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! */ + / * 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); } +*/ +s_act: BEGIN_ACTION nvlst ENDOBJ { dbgprintf("RRRR: action object\n"); } + | LEGACY_ACTION { dbgprintf("RRRR: legacy action\n"); } 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..8e74bde7 100644 --- a/grammar/lexer.l +++ b/grammar/lexer.l @@ -161,7 +161,7 @@ int fileno(FILE *stream); BEGIN INOBJ; return BEGINOBJ; } "module"[ \n\t]*"(" { yylval.objType = CNFOBJ_MODULE; BEGIN INOBJ; return BEGINOBJ; } -"action"[ \n\t]*"(" { BEGIN INOBJ; return BEGIN_ACTION; } +"action"[ \n\t]*"(" { dbgprintf("RRRR: lexer: %s\n", yytext); 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; } @@ -193,8 +193,10 @@ int fileno(FILE *stream); yyless(14); BEGIN INCL; } else { - yylval.s = strdup(yytext); - return CFSYSLINE; + /*yylval.s = strdup(yytext); + return CFSYSLINE;*/ + dbgprintf("RRRR: have CFSYSLINE/lexer: %s\n", yytext); + cnfDoCfsysline(strdup(yytext)); } } ![^ \t\n]+[ \t]*$ { yylval.s = strdup(yytext); return BSD_TAG_SELECTOR; } -- cgit v1.2.3 From 0bf6991bf6c155ff43c394c284e23dfe6b0fc53f Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 4 Sep 2012 10:50:07 +0200 Subject: new ruleengine: first code for stmt handling --- grammar/grammar.y | 54 +++++++++++++++++++++++++++++++------------------- grammar/lexer.l | 1 + grammar/rainerscript.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++- grammar/rainerscript.h | 22 ++++++++++++++++++++ 4 files changed, 110 insertions(+), 21 deletions(-) diff --git a/grammar/grammar.y b/grammar/grammar.y index ac0be30b..9051028a 100644 --- a/grammar/grammar.y +++ b/grammar/grammar.y @@ -9,7 +9,7 @@ * cases. So while we hope that cfsysline support can be dropped some time in * the future, we will probably keep these useful constructs. * - * Copyright 2011 Rainer Gerhards and Adiscon GmbH. + * Copyright 2011-2012 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * @@ -48,6 +48,7 @@ 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; @@ -75,6 +76,7 @@ extern int yyerror(char*); %token BSD_HOST_SELECTOR %token IF %token THEN +%token ELSE %token OR %token AND %token NOT @@ -100,6 +102,7 @@ extern int yyerror(char*); %type block */ %type expr +%type stmt block script /* %type rule %type scriptfilt @@ -112,15 +115,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 grammar.y" if more conflicts arise and check grammar.output 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 @@ -129,7 +126,8 @@ extern int yyerror(char*); */ conf: /* empty (to end recursion) */ | conf obj { cnfDoObj($2); } - | conf stmt { dbgprintf("RRRR: top-level stmt"); } + | conf stmt { dbgprintf("RRRR: top-level stmt:\n"); + cnfstmtPrint($2, 0); } | conf BSD_TAG_SELECTOR { cnfDoBSDTag($2); } | conf BSD_HOST_SELECTOR { cnfDoBSDHost($2); } obj: BEGINOBJ nvlst ENDOBJ { $$ = cnfobjNew($1, $2); } @@ -146,15 +144,31 @@ constant: BEGIN_CONSTANT nvlst ENDOBJ { $$ = cnfobjNew(CNFOBJ_CONSTANT, $2); } nvlst: { $$ = NULL; } | nvlst nv { $2->next = $1; $$ = $2; } nv: NAME '=' VALUE { $$ = nvlstNew($1, $3); } -script: stmt { dbgprintf("RRRR: root stmt\n"); } - | script stmt { dbgprintf("RRRR: stmt in list\n"); } -stmt: s_act { dbgprintf("RRRR: have s_act\n"); } - | STOP { dbgprintf("RRRR: have STOP\n"); } - | IF expr THEN block { dbgprintf("RRRR: have s_if \n"); } - | PRIFILT block { dbgprintf("RRRR: have s_prifilt\n"); } - | PROPFILT block { dbgprintf("RRRR: have s_propfilt\n"); } -block: stmt { dbgprintf("RRRR: have block:stmt\n"); } - | '{' script '}' { dbgprintf("RRRR: have block:script\n"); } +script: stmt { $$ = $1; dbgprintf("RRRR: root stmt\n"); } + | script stmt { $2->next = $1; $$ = $2; dbgprintf("RRRR: stmt in list\n"); } +stmt: s_act { $$ = cnfstmtNew(S_ACT); dbgprintf("RRRR: have s_act\n"); } + | STOP { $$ = cnfstmtNew(S_STOP); + dbgprintf("RRRR: have STOP\n"); } + | IF expr THEN block { $$ = cnfstmtNew(S_IF); + $$->d.cond.expr = $2; + $$->d.cond.t_then = $4; + $$->d.cond.t_else = NULL; + dbgprintf("RRRR: have s_if \n"); } + | IF expr THEN block ELSE block { $$ = cnfstmtNew(S_IF); + $$->d.cond.expr = $2; + $$->d.cond.t_then = $4; + $$->d.cond.t_else = $6; + dbgprintf("RRRR: have s_if \n"); } + | PRIFILT block { $$ = cnfstmtNew(S_PRIFILT); + $$->d.cond.expr = $1; + $$->d.cond.t_then = $2; + dbgprintf("RRRR: have s_prifilt\n"); } + | PROPFILT block { $$ = cnfstmtNew(S_PROPFILT); + $$->d.cond.expr = $1; + $$->d.cond.t_then = $2; + dbgprintf("RRRR: have s_propfilt\n"); } +block: stmt { $$ = $1; dbgprintf("RRRR: have block:stmt\n"); } + | '{' script '}' { $$ = $2; dbgprintf("RRRR: have block:script\n"); } /* rule: PRIFILT actlst { $$ = cnfruleNew(CNFFILT_PRI, $2); $$->filt.s = $1; } | PROPFILT actlst { $$ = cnfruleNew(CNFFILT_PROP, $2); $$->filt.s = $1; } diff --git a/grammar/lexer.l b/grammar/lexer.l index 8e74bde7..d603c449 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; } [0-9]+ { yylineno = atoi(yytext) - 1; } ")" { BEGIN INITIAL; } diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c index 33630a76..0d236c1e 100644 --- a/grammar/rainerscript.c +++ b/grammar/rainerscript.c @@ -107,7 +107,6 @@ objlstNew(struct cnfobj *o) lst->next = NULL; lst->obj = o; } -dbgprintf("AAAA: creating new objlst\n"); cnfobjPrint(o); return lst; @@ -1497,6 +1496,48 @@ cnfexprPrint(struct cnfexpr *expr, int indent) break; } } +void +cnfstmtPrint(struct cnfstmt *stmt, int indent) +{ + //dbgprintf("stmt %p, indent %d, type '%c'\n", expr, indent, expr->nodetype); + switch(stmt->nodetype) { + case S_STOP: + doIndent(indent); dbgprintf("STOP\n"); + break; + case S_ACT: + doIndent(indent); dbgprintf("ACTION %p\n", stmt->d.act); + break; + case S_IF: + doIndent(indent); dbgprintf("IF\n"); + cnfexprPrint(stmt->d.cond.expr, indent+1); + doIndent(indent); dbgprintf("THEN\n"); + cnfstmtPrint(stmt->d.cond.t_then, indent+1); + if(stmt->d.cond.t_else != NULL) { + doIndent(indent); dbgprintf("ELSE\n"); + cnfstmtPrint(stmt->d.cond.t_else, indent+1); + } + doIndent(indent); dbgprintf("END IF\n"); + break; + case S_PRIFILT: + doIndent(indent); dbgprintf("PRIFILT\n"); + cnfexprPrint(stmt->d.cond.expr, indent+1); + doIndent(indent); dbgprintf("THEN\n"); + cnfstmtPrint(stmt->d.cond.t_then, indent+1); + doIndent(indent); dbgprintf("END PRIFILT\n"); + break; + case S_PROPFILT: + doIndent(indent); dbgprintf("PROPFILT\n"); + cnfexprPrint(stmt->d.cond.expr, indent+1); + doIndent(indent); dbgprintf("THEN\n"); + cnfstmtPrint(stmt->d.cond.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) @@ -1531,6 +1572,17 @@ cnfvarNew(char *name) return var; } +struct cnfstmt * +cnfstmtNew(unsigned s_type) +{ + struct cnfstmt* cnfstmt; + if((cnfstmt = malloc(sizeof(struct cnfstmt))) != NULL) { + cnfstmt->nodetype = s_type; + cnfstmt->next = NULL; + } + return cnfstmt; +} + struct cnfrule * cnfruleNew(enum cnfFiltType filttype, struct cnfactlst *actlst) { diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h index 4c625cd8..3238b7fe 100644 --- a/grammar/rainerscript.h +++ b/grammar/rainerscript.h @@ -118,7 +118,14 @@ 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 + enum cnfFiltType { CNFFILT_NONE, CNFFILT_PRI, CNFFILT_PROP, CNFFILT_SCRIPT }; static inline char* cnfFiltType2str(enum cnfFiltType filttype) @@ -147,6 +154,19 @@ struct cnfrule { struct cnfactlst *actlst; }; +struct cnfstmt { /* base statement, for simple types */ + unsigned nodetype; + struct cnfstmt *next; + union { + struct { + struct cnfexpr *expr; + struct cnfstmt *t_then; + struct cnfstmt *t_else; + } cond; + struct action_s *act; + } d; +}; + struct cnfexpr { unsigned nodetype; struct cnfexpr *l; @@ -273,6 +293,8 @@ 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); rsRetVal initRainerscript(void); /* debug helper */ -- cgit v1.2.3 From 493ddeaa770de41ab5a6bb5279eed355c84b12ee Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 4 Sep 2012 11:05:19 +0200 Subject: new ruleengine: add &-operator (legacy action list) --- grammar/grammar.y | 13 ++++++++----- grammar/rainerscript.c | 4 ++-- grammar/rainerscript.h | 1 + 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/grammar/grammar.y b/grammar/grammar.y index 9051028a..6a5256d5 100644 --- a/grammar/grammar.y +++ b/grammar/grammar.y @@ -53,7 +53,7 @@ extern int yyerror(char*); struct objlst *objlst; struct cnfactlst *actlst; struct cnfexpr *expr; - struct cnfrule *rule; + /*struct cnfrule *rule;*/ struct cnffunc *func; struct cnffparamlst *fparams; } @@ -102,7 +102,7 @@ extern int yyerror(char*); %type block */ %type expr -%type stmt block script +%type stmt s_act actlst block script /* %type rule %type scriptfilt @@ -146,7 +146,7 @@ nvlst: { $$ = NULL; } nv: NAME '=' VALUE { $$ = nvlstNew($1, $3); } script: stmt { $$ = $1; dbgprintf("RRRR: root stmt\n"); } | script stmt { $2->next = $1; $$ = $2; dbgprintf("RRRR: stmt in list\n"); } -stmt: s_act { $$ = cnfstmtNew(S_ACT); dbgprintf("RRRR: have s_act\n"); } +stmt: actlst { $$ = $1; dbgprintf("RRRR: have stmt:actlst\n"); } | STOP { $$ = cnfstmtNew(S_STOP); dbgprintf("RRRR: have STOP\n"); } | IF expr THEN block { $$ = cnfstmtNew(S_IF); @@ -160,6 +160,7 @@ stmt: s_act { $$ = cnfstmtNew(S_ACT); dbgprintf("RRRR: have s_act\n"); } $$->d.cond.t_else = $6; dbgprintf("RRRR: have s_if \n"); } | PRIFILT block { $$ = cnfstmtNew(S_PRIFILT); + $$->d.cond.printable = $1; $$->d.cond.expr = $1; $$->d.cond.t_then = $2; dbgprintf("RRRR: have s_prifilt\n"); } @@ -169,6 +170,10 @@ stmt: s_act { $$ = cnfstmtNew(S_ACT); dbgprintf("RRRR: have s_act\n"); } dbgprintf("RRRR: have s_propfilt\n"); } block: stmt { $$ = $1; dbgprintf("RRRR: have block:stmt\n"); } | '{' script '}' { $$ = $2; dbgprintf("RRRR: have block:script\n"); } +actlst: s_act { $$ = $1; dbgprintf("RRRR: have s_act\n"); } + | actlst '&' s_act { $3->next = $1; $$ = $3; dbgprintf("RRRR: have actlst actlst:s_act\n"); } +s_act: BEGIN_ACTION nvlst ENDOBJ { $$ = cnfstmtNew(S_ACT); dbgprintf("RRRR: action object\n"); } + | LEGACY_ACTION { $$ = cnfstmtNew(S_ACT); dbgprintf("RRRR: legacy action\n"); } /* rule: PRIFILT actlst { $$ = cnfruleNew(CNFFILT_PRI, $2); $$->filt.s = $1; } | PROPFILT actlst { $$ = cnfruleNew(CNFFILT_PROP, $2); $$->filt.s = $1; } @@ -185,8 +190,6 @@ actlst: act { $$=$1; } | actlst cfsysline { $$ = cnfactlstAddSysline($1, $2); } | '{' block '}' { $$ = $2; } */ -s_act: BEGIN_ACTION nvlst ENDOBJ { dbgprintf("RRRR: action object\n"); } - | LEGACY_ACTION { dbgprintf("RRRR: legacy action\n"); } 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/rainerscript.c b/grammar/rainerscript.c index 0d236c1e..d9812fee 100644 --- a/grammar/rainerscript.c +++ b/grammar/rainerscript.c @@ -1519,8 +1519,8 @@ cnfstmtPrint(struct cnfstmt *stmt, int indent) doIndent(indent); dbgprintf("END IF\n"); break; case S_PRIFILT: - doIndent(indent); dbgprintf("PRIFILT\n"); - cnfexprPrint(stmt->d.cond.expr, indent+1); + doIndent(indent); dbgprintf("PRIFILT '%s'\n", stmt->d.cond.printable); + //cnfexprPrint(stmt->d.cond.expr, indent+1); doIndent(indent); dbgprintf("THEN\n"); cnfstmtPrint(stmt->d.cond.t_then, indent+1); doIndent(indent); dbgprintf("END PRIFILT\n"); diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h index 3238b7fe..1fe7f1b9 100644 --- a/grammar/rainerscript.h +++ b/grammar/rainerscript.h @@ -160,6 +160,7 @@ struct cnfstmt { /* base statement, for simple types */ union { struct { struct cnfexpr *expr; + uchar *printable; /* printable expr for debugging */ struct cnfstmt *t_then; struct cnfstmt *t_else; } cond; -- cgit v1.2.3 From 68b9fe72b89ff47efdbed8fea4185bac84279a51 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 4 Sep 2012 12:00:01 +0200 Subject: new ruleengine: script block correctly built --- grammar/grammar.y | 22 ++++++----- grammar/lexer.l | 2 +- grammar/rainerscript.c | 102 ++++++++++++++++++++++++++++++++----------------- grammar/rainerscript.h | 4 +- 4 files changed, 83 insertions(+), 47 deletions(-) diff --git a/grammar/grammar.y b/grammar/grammar.y index 6a5256d5..6e1fd913 100644 --- a/grammar/grammar.y +++ b/grammar/grammar.y @@ -145,8 +145,8 @@ nvlst: { $$ = NULL; } | nvlst nv { $2->next = $1; $$ = $2; } nv: NAME '=' VALUE { $$ = nvlstNew($1, $3); } script: stmt { $$ = $1; dbgprintf("RRRR: root stmt\n"); } - | script stmt { $2->next = $1; $$ = $2; dbgprintf("RRRR: stmt in list\n"); } -stmt: actlst { $$ = $1; dbgprintf("RRRR: have stmt:actlst\n"); } + | script stmt { $$ = scriptAddStmt($1, $2); dbgprintf("RRRR: stmt in list:\n");cnfstmtPrint($2, 0);dbgprintf("\n"); } +stmt: actlst { $$ = $1; dbgprintf("RRRR: have stmt:actlst %p\n", $1); } | STOP { $$ = cnfstmtNew(S_STOP); dbgprintf("RRRR: have STOP\n"); } | IF expr THEN block { $$ = cnfstmtNew(S_IF); @@ -160,20 +160,24 @@ stmt: actlst { $$ = $1; dbgprintf("RRRR: have stmt:actlst\n"); } $$->d.cond.t_else = $6; dbgprintf("RRRR: have s_if \n"); } | PRIFILT block { $$ = cnfstmtNew(S_PRIFILT); - $$->d.cond.printable = $1; + $$->printable = $1; $$->d.cond.expr = $1; $$->d.cond.t_then = $2; - dbgprintf("RRRR: have s_prifilt\n"); } + dbgprintf("RRRR: have s_prifilt %p\n", $2);cnfstmtPrint($2, 0);dbgprintf("\n"); } | PROPFILT block { $$ = cnfstmtNew(S_PROPFILT); $$->d.cond.expr = $1; $$->d.cond.t_then = $2; dbgprintf("RRRR: have s_propfilt\n"); } -block: stmt { $$ = $1; dbgprintf("RRRR: have block:stmt\n"); } +block: stmt { $$ = $1; dbgprintf("RRRR: have block:stmt %p\n", $1); } | '{' script '}' { $$ = $2; dbgprintf("RRRR: have block:script\n"); } -actlst: s_act { $$ = $1; dbgprintf("RRRR: have s_act\n"); } - | actlst '&' s_act { $3->next = $1; $$ = $3; dbgprintf("RRRR: have actlst actlst:s_act\n"); } -s_act: BEGIN_ACTION nvlst ENDOBJ { $$ = cnfstmtNew(S_ACT); dbgprintf("RRRR: action object\n"); } - | LEGACY_ACTION { $$ = cnfstmtNew(S_ACT); dbgprintf("RRRR: legacy action\n"); } +actlst: s_act { $$ = $1; dbgprintf("RRRR: have s_act, %p\n", $1); } + | actlst '&' s_act { $$ = scriptAddStmt($1, $3); dbgprintf("RRRR: have actlst actlst:s_act\n"); } +s_act: BEGIN_ACTION nvlst ENDOBJ { $$ = cnfstmtNew(S_ACT); + $$->printable="action()"; + dbgprintf("RRRR: action object\n"); } + | LEGACY_ACTION { $$ = cnfstmtNew(S_ACT); + $$->printable = $1; + dbgprintf("RRRR: legacy action\n"); } /* rule: PRIFILT actlst { $$ = cnfruleNew(CNFFILT_PRI, $2); $$->filt.s = $1; } | PROPFILT actlst { $$ = cnfruleNew(CNFFILT_PROP, $2); $$->filt.s = $1; } diff --git a/grammar/lexer.l b/grammar/lexer.l index d603c449..a56df4f8 100644 --- a/grammar/lexer.l +++ b/grammar/lexer.l @@ -165,7 +165,7 @@ int fileno(FILE *stream); "action"[ \n\t]*"(" { dbgprintf("RRRR: lexer: %s\n", yytext); 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; } +^[ \t]*[\*a-z][,\*a-z]*[0-7]*\.[,!=;\.\*a-z0-7]+ { yylval.s = strdup(rmLeadingSpace(yytext)); return PRIFILT; } "~" | "*" | \-\/[^*][^\n]* | diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c index 2d5bbd9b..b127b906 100644 --- a/grammar/rainerscript.c +++ b/grammar/rainerscript.c @@ -130,6 +130,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) { @@ -1498,45 +1517,47 @@ cnfexprPrint(struct cnfexpr *expr, int indent) } } void -cnfstmtPrint(struct cnfstmt *stmt, int indent) +cnfstmtPrint(struct cnfstmt *root, int indent) { + struct cnfstmt *stmt; //dbgprintf("stmt %p, indent %d, type '%c'\n", expr, indent, expr->nodetype); - switch(stmt->nodetype) { - case S_STOP: - doIndent(indent); dbgprintf("STOP\n"); - break; - case S_ACT: - doIndent(indent); dbgprintf("ACTION %p\n", stmt->d.act); - break; - case S_IF: - doIndent(indent); dbgprintf("IF\n"); - cnfexprPrint(stmt->d.cond.expr, indent+1); - doIndent(indent); dbgprintf("THEN\n"); - cnfstmtPrint(stmt->d.cond.t_then, indent+1); - if(stmt->d.cond.t_else != NULL) { - doIndent(indent); dbgprintf("ELSE\n"); - cnfstmtPrint(stmt->d.cond.t_else, indent+1); + for(stmt = root ; stmt != NULL ; stmt = stmt->next) { + switch(stmt->nodetype) { + 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.cond.expr, indent+1); + doIndent(indent); dbgprintf("THEN\n"); + cnfstmtPrint(stmt->d.cond.t_then, indent+1); + if(stmt->d.cond.t_else != NULL) { + doIndent(indent); dbgprintf("ELSE\n"); + cnfstmtPrint(stmt->d.cond.t_else, indent+1); + } + doIndent(indent); dbgprintf("END IF\n"); + break; + case S_PRIFILT: + doIndent(indent); dbgprintf("PRIFILT '%s'\n", stmt->printable); + //cnfexprPrint(stmt->d.cond.expr, indent+1); + cnfstmtPrint(stmt->d.cond.t_then, indent+1); + doIndent(indent); dbgprintf("END PRIFILT\n"); + break; + case S_PROPFILT: + doIndent(indent); dbgprintf("PROPFILT\n"); + cnfexprPrint(stmt->d.cond.expr, indent+1); + doIndent(indent); dbgprintf("THEN\n"); + cnfstmtPrint(stmt->d.cond.t_then, indent+1); + doIndent(indent); dbgprintf("END PROPFILT\n"); + break; + default: + dbgprintf("error: unknown stmt type %u\n", + (unsigned) stmt->nodetype); + break; } - doIndent(indent); dbgprintf("END IF\n"); - break; - case S_PRIFILT: - doIndent(indent); dbgprintf("PRIFILT '%s'\n", stmt->d.cond.printable); - //cnfexprPrint(stmt->d.cond.expr, indent+1); - doIndent(indent); dbgprintf("THEN\n"); - cnfstmtPrint(stmt->d.cond.t_then, indent+1); - doIndent(indent); dbgprintf("END PRIFILT\n"); - break; - case S_PROPFILT: - doIndent(indent); dbgprintf("PROPFILT\n"); - cnfexprPrint(stmt->d.cond.expr, indent+1); - doIndent(indent); dbgprintf("THEN\n"); - cnfstmtPrint(stmt->d.cond.t_then, indent+1); - doIndent(indent); dbgprintf("END PROPFILT\n"); - break; - default: - dbgprintf("error: unknown stmt type %u\n", - (unsigned) stmt->nodetype); - break; } } @@ -1873,6 +1894,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 1fe7f1b9..2d4d9271 100644 --- a/grammar/rainerscript.h +++ b/grammar/rainerscript.h @@ -157,10 +157,10 @@ struct cnfrule { struct cnfstmt { /* base statement, for simple types */ unsigned nodetype; struct cnfstmt *next; + uchar *printable; /* printable text for debugging */ union { struct { struct cnfexpr *expr; - uchar *printable; /* printable expr for debugging */ struct cnfstmt *t_then; struct cnfstmt *t_else; } cond; @@ -296,6 +296,8 @@ void cnfparamvalsDestruct(struct cnfparamvals *paramvals, struct cnfparamblk *bl 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); +char *rmLeadingSpace(char *s); rsRetVal initRainerscript(void); /* debug helper */ -- cgit v1.2.3 From b473bae2d7bd907b5e9a6ee9fc7cadf92dfe69b8 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 4 Sep 2012 12:35:36 +0200 Subject: new ruleengine: skeleton for reading conf file in place code still does not work, actual functions not implemented --- grammar/grammar.y | 48 +++++++++++++----------------------------------- grammar/parserif.h | 1 + runtime/rsconf.c | 8 ++++++++ runtime/ruleset.c | 20 +++++++++++++++++++- runtime/ruleset.h | 6 +++++- 5 files changed, 46 insertions(+), 37 deletions(-) diff --git a/grammar/grammar.y b/grammar/grammar.y index 6e1fd913..65a6e8dc 100644 --- a/grammar/grammar.y +++ b/grammar/grammar.y @@ -126,8 +126,7 @@ extern int yyerror(char*); */ conf: /* empty (to end recursion) */ | conf obj { cnfDoObj($2); } - | conf stmt { dbgprintf("RRRR: top-level stmt:\n"); - cnfstmtPrint($2, 0); } + | conf stmt { cnfDoScript($2); } | conf BSD_TAG_SELECTOR { cnfDoBSDTag($2); } | conf BSD_HOST_SELECTOR { cnfDoBSDHost($2); } obj: BEGINOBJ nvlst ENDOBJ { $$ = cnfobjNew($1, $2); } @@ -144,56 +143,35 @@ constant: BEGIN_CONSTANT nvlst ENDOBJ { $$ = cnfobjNew(CNFOBJ_CONSTANT, $2); } nvlst: { $$ = NULL; } | nvlst nv { $2->next = $1; $$ = $2; } nv: NAME '=' VALUE { $$ = nvlstNew($1, $3); } -script: stmt { $$ = $1; dbgprintf("RRRR: root stmt\n"); } - | script stmt { $$ = scriptAddStmt($1, $2); dbgprintf("RRRR: stmt in list:\n");cnfstmtPrint($2, 0);dbgprintf("\n"); } -stmt: actlst { $$ = $1; dbgprintf("RRRR: have stmt:actlst %p\n", $1); } - | STOP { $$ = cnfstmtNew(S_STOP); - dbgprintf("RRRR: have STOP\n"); } +script: stmt { $$ = $1; } + | script stmt { $$ = scriptAddStmt($1, $2); } +stmt: actlst { $$ = $1; } + | STOP { $$ = cnfstmtNew(S_STOP); } | IF expr THEN block { $$ = cnfstmtNew(S_IF); $$->d.cond.expr = $2; $$->d.cond.t_then = $4; - $$->d.cond.t_else = NULL; - dbgprintf("RRRR: have s_if \n"); } + $$->d.cond.t_else = NULL; } | IF expr THEN block ELSE block { $$ = cnfstmtNew(S_IF); $$->d.cond.expr = $2; $$->d.cond.t_then = $4; - $$->d.cond.t_else = $6; - dbgprintf("RRRR: have s_if \n"); } + $$->d.cond.t_else = $6; } | PRIFILT block { $$ = cnfstmtNew(S_PRIFILT); $$->printable = $1; $$->d.cond.expr = $1; - $$->d.cond.t_then = $2; - dbgprintf("RRRR: have s_prifilt %p\n", $2);cnfstmtPrint($2, 0);dbgprintf("\n"); } + $$->d.cond.t_then = $2; } | PROPFILT block { $$ = cnfstmtNew(S_PROPFILT); $$->d.cond.expr = $1; - $$->d.cond.t_then = $2; - dbgprintf("RRRR: have s_propfilt\n"); } -block: stmt { $$ = $1; dbgprintf("RRRR: have block:stmt %p\n", $1); } - | '{' script '}' { $$ = $2; dbgprintf("RRRR: have block:script\n"); } -actlst: s_act { $$ = $1; dbgprintf("RRRR: have s_act, %p\n", $1); } - | actlst '&' s_act { $$ = scriptAddStmt($1, $3); dbgprintf("RRRR: have actlst actlst:s_act\n"); } + $$->d.cond.t_then = $2; } +block: stmt { $$ = $1; } + | '{' script '}' { $$ = $2; } +actlst: s_act { $$ = $1; } + | actlst '&' s_act { $$ = scriptAddStmt($1, $3); } s_act: BEGIN_ACTION nvlst ENDOBJ { $$ = cnfstmtNew(S_ACT); $$->printable="action()"; dbgprintf("RRRR: action object\n"); } | LEGACY_ACTION { $$ = cnfstmtNew(S_ACT); $$->printable = $1; dbgprintf("RRRR: legacy action\n"); } -/* -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; } -*/ 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/parserif.h b/grammar/parserif.h index 597cfe40..3b2a9a7b 100644 --- a/grammar/parserif.h +++ b/grammar/parserif.h @@ -15,6 +15,7 @@ extern int yylineno; * these functions. */ void cnfDoObj(struct cnfobj *o); +void cnfDoScript(struct cnfstmt *script); void cnfDoRule(struct cnfrule *rule); void cnfDoCfsysline(char *ln); void cnfDoBSDTag(char *ln); diff --git a/runtime/rsconf.c b/runtime/rsconf.c index 5d2407ec..0f31e515 100644 --- a/runtime/rsconf.c +++ b/runtime/rsconf.c @@ -466,6 +466,14 @@ finalize_it: cnfruleDestruct(cnfrule); } +void cnfDoScript(struct cnfstmt *script) +{ + // 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) { DBGPRINTF("cnf:global:cfsysline: %s\n", ln); diff --git a/runtime/ruleset.c b/runtime/ruleset.c index 5cb34148..3bcfc4fb 100644 --- a/runtime/ruleset.c +++ b/runtime/ruleset.c @@ -11,7 +11,7 @@ * * 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. * @@ -248,6 +248,20 @@ GetParserList(rsconf_t *conf, msg_t *pMsg) } +/* Add a script block to the current ruleset */ +static void +addScript(ruleset_t *pThis, struct cnfstmt *script) +{ + if(pThis->last == NULL) + pThis->root = pThis->last = script; + else { + pThis->last->next = script; + pThis->last = script; + } +dbgprintf("RRRR: ruleset added script, script total now is:\n"); + cnfstmtPrint(pThis->root, 0); +} + /* 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. */ @@ -378,6 +392,8 @@ doRuleDestruct(void *pData) */ BEGINobjConstruct(ruleset) /* be sure to specify the object type also in END macro! */ CHKiRet(llInit(&pThis->llRules, doRuleDestruct, NULL, NULL)); + pThis->root = NULL; + pThis->last = NULL; finalize_it: ENDobjConstruct(ruleset) @@ -423,6 +439,7 @@ CODESTARTobjDestruct(ruleset) } llDestroy(&pThis->llRules); free(pThis->pszName); + // TODO: free rainerscript root (not look at last) ENDobjDestruct(ruleset) @@ -596,6 +613,7 @@ CODESTARTobjQueryInterface(ruleset) pIf->IterateAllActions = iterateAllActions; pIf->DestructAllActions = destructAllActions; pIf->AddRule = addRule; + pIf->AddScript = addScript; pIf->ProcessBatch = processBatch; pIf->SetName = setName; pIf->DebugPrintAll = debugPrintAll; diff --git a/runtime/ruleset.h b/runtime/ruleset.h index f4443e18..cc0c7a06 100644 --- a/runtime/ruleset.h +++ b/runtime/ruleset.h @@ -32,6 +32,8 @@ struct ruleset_s { 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 */ }; @@ -60,8 +62,10 @@ 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 */ + 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 */ -- cgit v1.2.3 From c596f1c1b2b6df18a9209d436a8255d96f437b54 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 4 Sep 2012 14:51:35 +0200 Subject: new ruleengine: PROP and PRI legacy filter structures properly created --- grammar/grammar.y | 23 ++++------ grammar/parserif.h | 1 - grammar/rainerscript.c | 86 ++++++++++++++++++++++++++++++++++---- grammar/rainerscript.h | 25 ++++++++++- runtime/conf.c | 111 +++++++++++++++++-------------------------------- runtime/conf.h | 4 +- runtime/rsconf.c | 5 +-- 7 files changed, 155 insertions(+), 100 deletions(-) diff --git a/grammar/grammar.y b/grammar/grammar.y index 65a6e8dc..a9f179e0 100644 --- a/grammar/grammar.y +++ b/grammar/grammar.y @@ -148,20 +148,15 @@ script: stmt { $$ = $1; } stmt: actlst { $$ = $1; } | STOP { $$ = cnfstmtNew(S_STOP); } | IF expr THEN block { $$ = cnfstmtNew(S_IF); - $$->d.cond.expr = $2; - $$->d.cond.t_then = $4; - $$->d.cond.t_else = NULL; } + $$->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.cond.expr = $2; - $$->d.cond.t_then = $4; - $$->d.cond.t_else = $6; } - | PRIFILT block { $$ = cnfstmtNew(S_PRIFILT); - $$->printable = $1; - $$->d.cond.expr = $1; - $$->d.cond.t_then = $2; } - | PROPFILT block { $$ = cnfstmtNew(S_PROPFILT); - $$->d.cond.expr = $1; - $$->d.cond.t_then = $2; } + $$->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; } @@ -170,7 +165,7 @@ s_act: BEGIN_ACTION nvlst ENDOBJ { $$ = cnfstmtNew(S_ACT); $$->printable="action()"; dbgprintf("RRRR: action object\n"); } | LEGACY_ACTION { $$ = cnfstmtNew(S_ACT); - $$->printable = $1; + $$->printable = (uchar*) $1; dbgprintf("RRRR: legacy action\n"); } expr: expr AND expr { $$ = cnfexprNew(AND, $1, $3); } | expr OR expr { $$ = cnfexprNew(OR, $1, $3); } diff --git a/grammar/parserif.h b/grammar/parserif.h index 3b2a9a7b..aa271ec4 100644 --- a/grammar/parserif.h +++ b/grammar/parserif.h @@ -16,7 +16,6 @@ extern int yylineno; */ void cnfDoObj(struct cnfobj *o); void cnfDoScript(struct cnfstmt *script); -void cnfDoRule(struct cnfrule *rule); void cnfDoCfsysline(char *ln); void cnfDoBSDTag(char *ln); void cnfDoBSDHost(char *ln); diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c index b127b906..0e3f30ae 100644 --- a/grammar/rainerscript.c +++ b/grammar/rainerscript.c @@ -37,6 +37,7 @@ #include #include "rsyslog.h" #include "rainerscript.h" +#include "conf.h" #include "parserif.h" #include "grammar.h" #include "queue.h" @@ -47,6 +48,37 @@ DEFobjCurrIf(obj) DEFobjCurrIf(regexp) +static 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) { @@ -1531,26 +1563,42 @@ cnfstmtPrint(struct cnfstmt *root, int indent) break; case S_IF: doIndent(indent); dbgprintf("IF\n"); - cnfexprPrint(stmt->d.cond.expr, indent+1); + cnfexprPrint(stmt->d.s_if.expr, indent+1); doIndent(indent); dbgprintf("THEN\n"); - cnfstmtPrint(stmt->d.cond.t_then, indent+1); - if(stmt->d.cond.t_else != NULL) { + 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.cond.t_else, indent+1); + 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); //cnfexprPrint(stmt->d.cond.expr, indent+1); - cnfstmtPrint(stmt->d.cond.t_then, indent+1); + cnfstmtPrint(stmt->d.s_prifilt.t_then, indent+1); doIndent(indent); dbgprintf("END PRIFILT\n"); break; case S_PROPFILT: doIndent(indent); dbgprintf("PROPFILT\n"); - cnfexprPrint(stmt->d.cond.expr, indent+1); + 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.cond.t_then, indent+1); + cnfstmtPrint(stmt->d.s_propfilt.t_then, indent+1); doIndent(indent); dbgprintf("END PROPFILT\n"); break; default: @@ -1605,6 +1653,30 @@ cnfstmtNew(unsigned s_type) return cnfstmt; } +struct cnfstmt * +cnfstmtNewPRIFILT(char *prifilt, struct cnfstmt *t_then) +{ + struct cnfstmt* cnfstmt; + if((cnfstmt = cnfstmtNew(S_PRIFILT)) != NULL) { + cnfstmt->printable = (uchar*)strdup(prifilt); + cnfstmt->d.s_prifilt.t_then = t_then; + DecodePRIFilter((uchar*)prifilt, cnfstmt->d.s_prifilt.pmask); + } + return cnfstmt; +} + +struct cnfstmt * +cnfstmtNewPROPFILT(char *propfilt, struct cnfstmt *t_then) +{ + struct cnfstmt* cnfstmt; + if((cnfstmt = cnfstmtNew(S_PROPFILT)) != NULL) { + cnfstmt->printable = (uchar*)strdup(propfilt); + cnfstmt->d.s_propfilt.t_then = t_then; + DecodePropFilter((uchar*)propfilt, cnfstmt); + } + return cnfstmt; +} + struct cnfrule * cnfruleNew(enum cnfFiltType filttype, struct cnfactlst *actlst) { diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h index 2d4d9271..89d7c050 100644 --- a/grammar/rainerscript.h +++ b/grammar/rainerscript.h @@ -3,7 +3,14 @@ #include #include #include +#include +#include +//#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). @@ -163,7 +170,20 @@ struct cnfstmt { /* base statement, for simple types */ struct cnfexpr *expr; struct cnfstmt *t_then; struct cnfstmt *t_else; - } cond; + } 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; }; @@ -297,7 +317,10 @@ 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); rsRetVal initRainerscript(void); /* debug helper */ diff --git a/runtime/conf.c b/runtime/conf.c index 488d1b86..7ad8f529 100644 --- a/runtime/conf.c +++ b/runtime/conf.c @@ -65,13 +65,13 @@ #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 */ @@ -326,14 +326,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 +342,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 +399,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<f_filterData.f_pmask[i] |= (1<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<f_filterData.f_pmask[i] |= (1<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<> 3] &= ~(1<f_filterData.f_pmask[i >> 3] |= (1<> 3] |= (1<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<> 3] &= ~(1<f_filterData.f_pmask[i >> 3] |= (1<> 3] |= (1<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 +500,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 +531,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 +570,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); } 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 0f31e515..5f1980fd 100644 --- a/runtime/rsconf.c +++ b/runtime/rsconf.c @@ -370,9 +370,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); @@ -415,6 +412,7 @@ void cnfDoObj(struct cnfobj *o) cnfobjDestruct(o); } +#if 0 void cnfDoRule(struct cnfrule *cnfrule) { rule_t *pRule; @@ -465,6 +463,7 @@ finalize_it: //TODO: do something with error states cnfruleDestruct(cnfrule); } +#endif void cnfDoScript(struct cnfstmt *script) { -- cgit v1.2.3 From 72f9fe88b24428067557a71405ee641a641bf7c4 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 4 Sep 2012 15:18:37 +0200 Subject: new ruleengine: v6+ action object properly constructed --- grammar/grammar.y | 2 +- grammar/rainerscript.c | 17 +++++++++++++++++ grammar/rainerscript.h | 2 ++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/grammar/grammar.y b/grammar/grammar.y index a9f179e0..f94cec04 100644 --- a/grammar/grammar.y +++ b/grammar/grammar.y @@ -161,7 +161,7 @@ block: stmt { $$ = $1; } | '{' script '}' { $$ = $2; } actlst: s_act { $$ = $1; } | actlst '&' s_act { $$ = scriptAddStmt($1, $3); } -s_act: BEGIN_ACTION nvlst ENDOBJ { $$ = cnfstmtNew(S_ACT); +s_act: BEGIN_ACTION nvlst ENDOBJ { $$ = cnfstmtNewAct($2); $$->printable="action()"; dbgprintf("RRRR: action object\n"); } | LEGACY_ACTION { $$ = cnfstmtNew(S_ACT); diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c index 0e3f30ae..6e3bae68 100644 --- a/grammar/rainerscript.c +++ b/grammar/rainerscript.c @@ -1677,6 +1677,23 @@ cnfstmtNewPROPFILT(char *propfilt, struct cnfstmt *t_then) 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*)"action()"; +done: return cnfstmt; +} + struct cnfrule * cnfruleNew(enum cnfFiltType filttype, struct cnfactlst *actlst) { diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h index 89d7c050..978f08ad 100644 --- a/grammar/rainerscript.h +++ b/grammar/rainerscript.h @@ -132,6 +132,7 @@ struct cnfactlst { #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* @@ -321,6 +322,7 @@ 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); rsRetVal initRainerscript(void); /* debug helper */ -- cgit v1.2.3 From 3dd73d7f7194139a9b8bf1668f6192ead0c801ec Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 4 Sep 2012 15:54:40 +0200 Subject: new ruleengine: legacy action object properly constructed --- grammar/grammar.y | 8 ++------ grammar/rainerscript.c | 25 +++++++++++++++++++++++++ grammar/rainerscript.h | 1 + 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/grammar/grammar.y b/grammar/grammar.y index f94cec04..db599c5b 100644 --- a/grammar/grammar.y +++ b/grammar/grammar.y @@ -161,12 +161,8 @@ block: stmt { $$ = $1; } | '{' script '}' { $$ = $2; } actlst: s_act { $$ = $1; } | actlst '&' s_act { $$ = scriptAddStmt($1, $3); } -s_act: BEGIN_ACTION nvlst ENDOBJ { $$ = cnfstmtNewAct($2); - $$->printable="action()"; - dbgprintf("RRRR: action object\n"); } - | LEGACY_ACTION { $$ = cnfstmtNew(S_ACT); - $$->printable = (uchar*) $1; - dbgprintf("RRRR: legacy action\n"); } +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/rainerscript.c b/grammar/rainerscript.c index 6e3bae68..20cf2f6d 100644 --- a/grammar/rainerscript.c +++ b/grammar/rainerscript.c @@ -39,6 +39,7 @@ #include "rainerscript.h" #include "conf.h" #include "parserif.h" +#include "rsconf.h" #include "grammar.h" #include "queue.h" #include "srUtils.h" @@ -1555,6 +1556,9 @@ cnfstmtPrint(struct cnfstmt *root, int indent) //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; @@ -1694,6 +1698,27 @@ cnfstmtNewAct(struct nvlst *lst) done: return cnfstmt; } +struct cnfstmt * +cnfstmtNewLegaAct(uchar *actline) +{ + struct cnfstmt* cnfstmt; + rsRetVal localRet; + if((cnfstmt = cnfstmtNew(S_ACT)) == NULL) + goto done; + cnfstmt->printable = (uchar*)strdup((char*)actline); + localRet = cflineDoAction(loadConf, &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 cnfrule * cnfruleNew(enum cnfFiltType filttype, struct cnfactlst *actlst) { diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h index 978f08ad..d69dd041 100644 --- a/grammar/rainerscript.h +++ b/grammar/rainerscript.h @@ -323,6 +323,7 @@ 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(uchar *actline); rsRetVal initRainerscript(void); /* debug helper */ -- cgit v1.2.3 From 7bf910ac461468c6b452be13ce9f4a7267641d31 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 4 Sep 2012 17:25:22 +0200 Subject: switch ruleset.h to ASL 2.0 There was a single contribution from varmojfekoj, and that has been removed some time ago. So I am the sole copyright holder and can change the license. --- runtime/ruleset.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/runtime/ruleset.c b/runtime/ruleset.c index 3bcfc4fb..4f714ec1 100644 --- a/runtime/ruleset.c +++ b/runtime/ruleset.c @@ -15,21 +15,19 @@ * * 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 . - * - * 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" -- cgit v1.2.3 From d3e96418f514cd69592be24af6a632a8491820fc Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 6 Sep 2012 10:48:24 +0200 Subject: new ruleengine: implement rainerscript execution engine --- grammar/lexer.l | 2 +- grammar/rainerscript.c | 2 +- grammar/rainerscript.h | 1 + runtime/rule.c | 2 + runtime/ruleset.c | 278 ++++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 282 insertions(+), 3 deletions(-) diff --git a/grammar/lexer.l b/grammar/lexer.l index a56df4f8..51b0fbd2 100644 --- a/grammar/lexer.l +++ b/grammar/lexer.l @@ -164,7 +164,7 @@ int fileno(FILE *stream); BEGIN INOBJ; return BEGINOBJ; } "action"[ \n\t]*"(" { dbgprintf("RRRR: lexer: %s\n", yytext); BEGIN INOBJ; return BEGIN_ACTION; } ^[ \t]*:\$?[a-z\-]+[ ]*,[ ]*!?[a-z]+[ ]*,[ ]*\".*\" { - yylval.s = strdup(yytext); return PROPFILT; } + yylval.s = strdup(rmLeadingSpace(yytext)); return PROPFILT; } ^[ \t]*[\*a-z][,\*a-z]*[0-7]*\.[,!=;\.\*a-z0-7]+ { yylval.s = strdup(rmLeadingSpace(yytext)); return PRIFILT; } "~" | "*" | diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c index 20cf2f6d..dc2ef64c 100644 --- a/grammar/rainerscript.c +++ b/grammar/rainerscript.c @@ -49,7 +49,7 @@ DEFobjCurrIf(obj) DEFobjCurrIf(regexp) -static char* +char* getFIOPName(unsigned iFIOP) { char *pRet; diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h index d69dd041..f41084c8 100644 --- a/grammar/rainerscript.h +++ b/grammar/rainerscript.h @@ -324,6 +324,7 @@ 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(uchar *actline); +char* getFIOPName(unsigned iFIOP); rsRetVal initRainerscript(void); /* debug helper */ 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 4f714ec1..45520451 100644 --- a/runtime/ruleset.c +++ b/runtime/ruleset.c @@ -46,6 +46,9 @@ #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 */ @@ -56,6 +59,7 @@ 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) ---------- */ @@ -205,6 +209,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<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 @@ -224,7 +500,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)); } -- cgit v1.2.3 From 200e08ac4252a0a0eca31a441e63688179baebb1 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 6 Sep 2012 11:09:16 +0200 Subject: new ruleengine: some cleanup --- runtime/Makefile.am | 2 -- runtime/conf.c | 4 ---- runtime/rsconf.c | 38 -------------------------------------- runtime/rsyslog.c | 3 --- runtime/ruleset.c | 52 ++-------------------------------------------------- runtime/ruleset.h | 4 ++-- tools/syslogd.c | 5 ----- 7 files changed, 4 insertions(+), 104 deletions(-) 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 7ad8f529..8edf02fc 100644 --- a/runtime/conf.c +++ b/runtime/conf.c @@ -61,7 +61,6 @@ #include "srUtils.h" #include "errmsg.h" #include "net.h" -#include "rule.h" #include "ruleset.h" #include "rsconf.h" #include "unicode-helper.h" @@ -79,7 +78,6 @@ DEFobjStaticHelpers DEFobjCurrIf(module) DEFobjCurrIf(errmsg) DEFobjCurrIf(net) -DEFobjCurrIf(rule) DEFobjCurrIf(ruleset) int bConfStrictScoping = 0; /* force strict scoping during config processing? */ @@ -798,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) @@ -812,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/rsconf.c b/runtime/rsconf.c index 5f1980fd..d2bfd5fa 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,40 +240,6 @@ CODESTARTobjDebugPrint(rsconf) ENDobjDebugPrint(rsconf) -rsRetVal -cnfDoActlst(struct cnfactlst *actlst, rule_t *pRule) -{ - struct cnfcfsyslinelst *cflst; - action_t *pAction; - uchar *str; - 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; - CHKiRet(cflineDoAction(loadConf, &str, &pAction)); - 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 @@ -1370,7 +1334,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)); @@ -1387,7 +1350,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..73d3bd43 100644 --- a/runtime/rsyslog.c +++ b/runtime/rsyslog.c @@ -171,8 +171,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 +218,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/ruleset.c b/runtime/ruleset.c index 45520451..f09bebdd 100644 --- a/runtime/ruleset.c +++ b/runtime/ruleset.c @@ -136,23 +136,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 @@ -536,31 +519,6 @@ dbgprintf("RRRR: ruleset added script, script total now is:\n"); cnfstmtPrint(pThis->root, 0); } -/* 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) -{ - 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); - } - -finalize_it: - RETiRet; -} - /* set name for ruleset */ static rsRetVal setName(ruleset_t *pThis, uchar *pszName) @@ -747,16 +705,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) @@ -886,7 +839,6 @@ CODESTARTobjQueryInterface(ruleset) pIf->IterateAllActions = iterateAllActions; pIf->DestructAllActions = destructAllActions; - pIf->AddRule = addRule; pIf->AddScript = addScript; pIf->ProcessBatch = processBatch; pIf->SetName = setName; @@ -918,7 +870,7 @@ 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)); +//TODO:finally delete! CHKiRet(objUse(rule, CORE_COMPONENT)); /* set our own handlers */ OBJSetMethodHandler(objMethod_DEBUGPRINT, rulesetDebugPrint); diff --git a/runtime/ruleset.h b/runtime/ruleset.h index cc0c7a06..1a903aee 100644 --- a/runtime/ruleset.h +++ b/runtime/ruleset.h @@ -44,9 +44,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*); @@ -63,6 +61,8 @@ BEGINinterface(ruleset) /* name must also be changed in ENDinterface macro! */ * 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 7 /* increment whenever you change the interface structure! */ 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); -- cgit v1.2.3 From 77ea54a5b98e80738914587bd0f252befeffe4f7 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 6 Sep 2012 17:17:50 +0200 Subject: new ruleengine: restore action iterator functionality --- grammar/rainerscript.c | 4 +-- grammar/rainerscript.h | 2 +- runtime/ruleset.c | 84 +++++++++++++++++++++++--------------------------- runtime/ruleset.h | 1 - 4 files changed, 41 insertions(+), 50 deletions(-) diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c index dc2ef64c..0ebfb44e 100644 --- a/grammar/rainerscript.c +++ b/grammar/rainerscript.c @@ -1699,14 +1699,14 @@ done: return cnfstmt; } struct cnfstmt * -cnfstmtNewLegaAct(uchar *actline) +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, &actline, &cnfstmt->d.act); + 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", diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h index f41084c8..b7d13a65 100644 --- a/grammar/rainerscript.h +++ b/grammar/rainerscript.h @@ -323,7 +323,7 @@ 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(uchar *actline); +struct cnfstmt * cnfstmtNewLegaAct(char *actline); char* getFIOPName(unsigned iFIOP); rsRetVal initRainerscript(void); diff --git a/runtime/ruleset.c b/runtime/ruleset.c index f09bebdd..30254f0c 100644 --- a/runtime/ruleset.c +++ b/runtime/ruleset.c @@ -40,7 +40,6 @@ #include "cfsysline.h" #include "msg.h" #include "ruleset.h" -#include "rule.h" #include "errmsg.h" #include "parser.h" #include "batch.h" @@ -54,7 +53,6 @@ /* static data */ DEFobjStaticHelpers DEFobjCurrIf(errmsg) -DEFobjCurrIf(rule) DEFobjCurrIf(parser) /* forward definitions */ @@ -75,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, ¶ms)); - -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. @@ -608,25 +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)); pThis->root = NULL; pThis->last = NULL; -finalize_it: ENDobjConstruct(ruleset) @@ -669,7 +664,6 @@ CODESTARTobjDestruct(ruleset) if(pThis->pParserLst != NULL) { parser.DestructParserList(&pThis->pParserLst); } - llDestroy(&pThis->llRules); free(pThis->pszName); // TODO: free rainerscript root (not look at last) ENDobjDestruct(ruleset) @@ -858,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) @@ -870,7 +863,6 @@ ENDObjClassExit(ruleset) BEGINObjClassInit(ruleset, 1, OBJ_IS_CORE_MODULE) /* class, version */ /* request objects we use */ CHKiRet(objUse(errmsg, CORE_COMPONENT)); -//TODO:finally delete! CHKiRet(objUse(rule, CORE_COMPONENT)); /* set our own handlers */ OBJSetMethodHandler(objMethod_DEBUGPRINT, rulesetDebugPrint); diff --git a/runtime/ruleset.h b/runtime/ruleset.h index 1a903aee..50c8071e 100644 --- a/runtime/ruleset.h +++ b/runtime/ruleset.h @@ -29,7 +29,6 @@ /* 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; -- cgit v1.2.3 From 8795df908b969f6e226256a3cd25cc976491533b Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 6 Sep 2012 18:23:16 +0200 Subject: new ruleengine: properly freeing stmt tree --- grammar/lexer.l | 4 +--- grammar/rainerscript.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++- grammar/rainerscript.h | 1 + runtime/ruleset.c | 2 +- 4 files changed, 53 insertions(+), 5 deletions(-) diff --git a/grammar/lexer.l b/grammar/lexer.l index 51b0fbd2..b0f4bba9 100644 --- a/grammar/lexer.l +++ b/grammar/lexer.l @@ -172,9 +172,7 @@ int fileno(FILE *stream); \/[^*][^\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; } ")" { BEGIN INITIAL; return ENDOBJ; } [a-z][a-z0-9_\.]* { yylval.estr = es_newStrFromCStr(yytext, yyleng); return NAME; } diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c index 0ebfb44e..d6a51191 100644 --- a/grammar/rainerscript.c +++ b/grammar/rainerscript.c @@ -1635,6 +1635,7 @@ cnfstringvalNew(es_str_t *estr) return strval; } + struct cnfvar* cnfvarNew(char *name) { @@ -1657,12 +1658,57 @@ cnfstmtNew(unsigned s_type) return cnfstmt; } +void +cnfstmtDestruct(struct cnfstmt *root) +{ + struct cnfstmt *stmt, *todel; + for(stmt = root ; stmt != NULL ; ) { + switch(stmt->nodetype) { + case S_NOP: + case S_STOP: + break; + case S_ACT: +dbgprintf("XXXX: destruct action %p\n", stmt->d.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; + } + todel = stmt; + stmt = stmt->next; + free(todel); + } +} + struct cnfstmt * cnfstmtNewPRIFILT(char *prifilt, struct cnfstmt *t_then) { struct cnfstmt* cnfstmt; if((cnfstmt = cnfstmtNew(S_PRIFILT)) != NULL) { - cnfstmt->printable = (uchar*)strdup(prifilt); + cnfstmt->printable = (uchar*)prifilt; cnfstmt->d.s_prifilt.t_then = t_then; DecodePRIFilter((uchar*)prifilt, cnfstmt->d.s_prifilt.pmask); } @@ -1676,6 +1722,9 @@ cnfstmtNewPROPFILT(char *propfilt, struct cnfstmt *t_then) if((cnfstmt = cnfstmtNew(S_PROPFILT)) != NULL) { cnfstmt->printable = (uchar*)strdup(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; diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h index b7d13a65..2f4aec8a 100644 --- a/grammar/rainerscript.h +++ b/grammar/rainerscript.h @@ -324,6 +324,7 @@ 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); diff --git a/runtime/ruleset.c b/runtime/ruleset.c index 30254f0c..74f078b6 100644 --- a/runtime/ruleset.c +++ b/runtime/ruleset.c @@ -665,7 +665,7 @@ CODESTARTobjDestruct(ruleset) parser.DestructParserList(&pThis->pParserLst); } free(pThis->pszName); - // TODO: free rainerscript root (not look at last) + cnfstmtDestruct(pThis->root); ENDobjDestruct(ruleset) -- cgit v1.2.3 From 819963d892f5614cc08ba9b7b259405643aa5b3d Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 7 Sep 2012 12:54:22 +0200 Subject: new ruleengine: cleanup --- runtime/rsconf.c | 53 ----------------------------------------------------- runtime/rsyslog.c | 1 - 2 files changed, 54 deletions(-) diff --git a/runtime/rsconf.c b/runtime/rsconf.c index d2bfd5fa..565bc597 100644 --- a/runtime/rsconf.c +++ b/runtime/rsconf.c @@ -376,59 +376,6 @@ void cnfDoObj(struct cnfobj *o) cnfobjDestruct(o); } -#if 0 -void cnfDoRule(struct cnfrule *cnfrule) -{ - 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); -} -#endif - void cnfDoScript(struct cnfstmt *script) { // TODO: streamline this, call directly into ruleset from grammar.y diff --git a/runtime/rsyslog.c b/runtime/rsyslog.c index 73d3bd43..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" -- cgit v1.2.3 From 92c030bb767b7f7306a3b8d015b901bb8f1f79b9 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 10 Sep 2012 16:59:20 +0200 Subject: new ruleengine: more cleanup --- grammar/grammar.y | 8 +-- grammar/rainerscript.c | 169 +------------------------------------------------ grammar/rainerscript.h | 36 ----------- 3 files changed, 3 insertions(+), 210 deletions(-) diff --git a/grammar/grammar.y b/grammar/grammar.y index db599c5b..65793fb1 100644 --- a/grammar/grammar.y +++ b/grammar/grammar.y @@ -6,8 +6,7 @@ * 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-2012 Rainer Gerhards and Adiscon GmbH. * @@ -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*); %} @@ -51,9 +50,7 @@ extern int yyerror(char*); struct cnfstmt *stmt; struct nvlst *nvlst; struct objlst *objlst; - struct cnfactlst *actlst; struct cnfexpr *expr; - /*struct cnfrule *rule;*/ struct cnffunc *func; struct cnffparamlst *fparams; } @@ -63,7 +60,6 @@ extern int yyerror(char*); %token FUNC %token BEGINOBJ %token ENDOBJ -%token CFSYSLINE %token BEGIN_ACTION %token BEGIN_PROPERTY %token BEGIN_CONSTANT diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c index d6a51191..295e46b6 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. * @@ -712,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) { @@ -1768,63 +1658,6 @@ cnfstmtNewLegaAct(char *actline) done: return cnfstmt; } -struct cnfrule * -cnfruleNew(enum cnfFiltType filttype, struct cnfactlst *actlst) -{ - struct cnfrule* cnfrule; - if((cnfrule = malloc(sizeof(struct cnfrule))) != NULL) { - cnfrule->nodetype = 'R'; - cnfrule->filttype = filttype; - cnfrule->actlst = cnfactlstReverse(actlst); - } - return cnfrule; -} - -void -cnfrulePrint(struct cnfrule *rule) -{ - 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; - } - 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 cnfcfsyslinelst *toDel; - while(cfslst != NULL) { - toDel = cfslst; - cfslst = cfslst->next; - free(toDel); - } -} - -void -cnfruleDestruct(struct cnfrule *rule) -{ - if( rule->filttype == CNFFILT_PRI - || rule->filttype == CNFFILT_PROP) - free(rule->filt.s); - cnfactlstDestruct(rule->actlst); - free(rule); -} - struct cnffparamlst * cnffparamlstNew(struct cnfexpr *expr, struct cnffparamlst *next) { diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h index 2f4aec8a..a8d48632 100644 --- a/grammar/rainerscript.h +++ b/grammar/rainerscript.h @@ -98,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. * @@ -152,16 +135,6 @@ cnfFiltType2str(enum cnfFiltType filttype) } -struct cnfrule { - unsigned nodetype; - enum cnfFiltType filttype; - union { - char *s; - struct cnfexpr *expr; - } filt; - struct cnfactlst *actlst; -}; - struct cnfstmt { /* base statement, for simple types */ unsigned nodetype; struct cnfstmt *next; @@ -289,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); @@ -301,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); @@ -314,7 +279,6 @@ 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); -- cgit v1.2.3 From d3bb43798c95f9d95f9e031387f4aedd814c34ab Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 10 Sep 2012 18:17:34 +0200 Subject: new ruleengine: fix memory leaks & a little cleanup --- grammar/lexer.l | 5 +---- grammar/rainerscript.c | 8 ++++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/grammar/lexer.l b/grammar/lexer.l index b0f4bba9..c52e5a01 100644 --- a/grammar/lexer.l +++ b/grammar/lexer.l @@ -162,7 +162,7 @@ int fileno(FILE *stream); BEGIN INOBJ; return BEGINOBJ; } "module"[ \n\t]*"(" { yylval.objType = CNFOBJ_MODULE; BEGIN INOBJ; return BEGINOBJ; } -"action"[ \n\t]*"(" { dbgprintf("RRRR: lexer: %s\n", yytext); BEGIN INOBJ; return BEGIN_ACTION; } +"action"[ \n\t]*"(" { BEGIN INOBJ; return BEGIN_ACTION; } ^[ \t]*:\$?[a-z\-]+[ ]*,[ ]*!?[a-z]+[ ]*,[ ]*\".*\" { yylval.s = strdup(rmLeadingSpace(yytext)); return PROPFILT; } ^[ \t]*[\*a-z][,\*a-z]*[0-7]*\.[,!=;\.\*a-z0-7]+ { yylval.s = strdup(rmLeadingSpace(yytext)); return PRIFILT; } @@ -192,9 +192,6 @@ int fileno(FILE *stream); yyless(14); BEGIN INCL; } else { - /*yylval.s = strdup(yytext); - return CFSYSLINE;*/ - dbgprintf("RRRR: have CFSYSLINE/lexer: %s\n", yytext); cnfDoCfsysline(strdup(yytext)); } } diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c index 295e46b6..30600ea3 100644 --- a/grammar/rainerscript.c +++ b/grammar/rainerscript.c @@ -1468,7 +1468,6 @@ cnfstmtPrint(struct cnfstmt *root, int indent) break; case S_PRIFILT: doIndent(indent); dbgprintf("PRIFILT '%s'\n", stmt->printable); - //cnfexprPrint(stmt->d.cond.expr, indent+1); cnfstmtPrint(stmt->d.s_prifilt.t_then, indent+1); doIndent(indent); dbgprintf("END PRIFILT\n"); break; @@ -1543,6 +1542,7 @@ cnfstmtNew(unsigned s_type) struct cnfstmt* cnfstmt; if((cnfstmt = malloc(sizeof(struct cnfstmt))) != NULL) { cnfstmt->nodetype = s_type; + cnfstmt->printable = NULL; cnfstmt->next = NULL; } return cnfstmt; @@ -1558,7 +1558,6 @@ cnfstmtDestruct(struct cnfstmt *root) case S_STOP: break; case S_ACT: -dbgprintf("XXXX: destruct action %p\n", stmt->d.act); actionDestruct(stmt->d.act); break; case S_IF: @@ -1587,6 +1586,7 @@ dbgprintf("XXXX: destruct action %p\n", stmt->d.act); (unsigned) stmt->nodetype); break; } + free(stmt->printable); todel = stmt; stmt = stmt->next; free(todel); @@ -1610,7 +1610,7 @@ cnfstmtNewPROPFILT(char *propfilt, struct cnfstmt *t_then) { struct cnfstmt* cnfstmt; if((cnfstmt = cnfstmtNew(S_PROPFILT)) != NULL) { - cnfstmt->printable = (uchar*)strdup(propfilt); + 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; @@ -1633,7 +1633,7 @@ cnfstmtNewAct(struct nvlst *lst) cnfstmt->nodetype = S_NOP; /* disable action! */ goto done; } - cnfstmt->printable = (uchar*)"action()"; + cnfstmt->printable = (uchar*)strdup("action()"); done: return cnfstmt; } -- cgit v1.2.3