From 50ddd3fd7de672a2fa2df67adb27401cc38ce38c Mon Sep 17 00:00:00 2001
From: Rainer Gerhards
Below is the formal language definitionin ABNF (RFC 2234)
format:
; all of this is a working document and may change! -- rgerhards, 2008-02-24+
script := *stmt
stmt := (if_stmt / block / vardef / run_s / load_s)
vardef := "var" ["scope" = ("global" / "event")]
block := "begin" stmt "end"
load_s := "load" constraint ("module") modpath params ; load mod only if expr is true
run_s := "run" constraint ("input") name
constraint:= "if" expr ; constrains some one-time commands
modpath := expr
params := ["params" *1param *("," param) "endparams"]
param := paramname) "=" expr
paramname := [*(obqualifier ".") name]
modpath:= ; path to module
?line? := cfsysline / cfli
cfsysline:= BOL "$" *char EOL ; how to handle the first line? (no EOL in front!)
BOL := ; Begin of Line - implicitely set on file beginning and after each EOL
EOL := 0x0a ;LF
if_stmt := "if" expr "then"
old_filter:= BOL facility "." severity ; no whitespace allowed between BOL and facility!
facility := "*" / "auth" / "authpriv" / "cron" / "daemon" / "kern" / "lpr" /
"mail" / "mark" / "news" / "security" / "syslog" / "user" / "uucp" /
"local0" .. "local7" / "mark"
; The keyword security should not be used anymore
; mark is just internal
severity := TBD ; not really relevant in this context
; and now the actual expression
expr := e_and *("or" e_and)
e_and := e_cmp *("and" e_cmp)
e_cmp := val 0*1(cmp_op val)
val := term *(("+" / "-") term)
term := factor *(("*" / "/" / "%") factor)
factor := ["not"] ["-"] terminal
terminal := var / constant / function / ( "(" expr ")" )
function := name "(" *("," expr) ")"
var := "$" varname
varname := msgvar / sysvar
msgvar := name
sysvar := "$" name
name := alpha *(alnum)
constant := string / number
string := simpstr / tplstr ; tplstr will be implemented in next phase
simpstr := "'" *char "'" ; use your imagination for char ;)
tplstr := '"' template '"' ; not initially implemented
number := ["-"] 1*digit ; 0nn = octal, 0xnn = hex, nn = decimal
cmp_op := "==" / "!=" / "<>" / "<" / ">" / "<=" / ">=" / "contains" / "startswith"
digit := %x30-39
alpha := "a" ... "z" # all letters
alnum :* alpha / digit / "_"
; all of this is a working document and may change! -- rgerhards, 2008-02-24
script := *stmt
stmt := (if_stmt / block / vardef / run_s / load_s)
vardef := "var" ["scope" = ("global" / "event")]
block := "begin" stmt "end"
load_s := "load" constraint ("module") modpath params ; load mod only if expr is true
run_s := "run" constraint ("input") name
constraint:= "if" expr ; constrains some one-time commands
modpath := expr
params := ["params" *1param *("," param) "endparams"]
param := paramname) "=" expr
paramname := [*(obqualifier ".") name]
modpath:= ; path to module
?line? := cfsysline / cfli
cfsysline:= BOL "$" *char EOL ; how to handle the first line? (no EOL in front!)
BOL := ; Begin of Line - implicitely set on file beginning and after each EOL
EOL := 0x0a ;LF
if_stmt := "if" expr "then"
old_filter:= BOL facility "." severity ; no whitespace allowed between BOL and facility!
facility := "*" / "auth" / "authpriv" / "cron" / "daemon" / "kern" / "lpr" /
"mail" / "mark" / "news" / "security" / "syslog" / "user" / "uucp" /
"local0" .. "local7" / "mark"
; The keyword security should not be used anymore
; mark is just internal
severity := TBD ; not really relevant in this context
; and now the actual expression
expr := e_and *("or" e_and)
e_and := e_cmp *("and" e_cmp)
e_cmp := val 0*1(cmp_op val)
val := term *(("+" / "-" / "&") term)
term := factor *(("*" / "/" / "%") factor)
factor := ["not"] ["-"] terminal
terminal := var / constant / function / ( "(" expr ")" )
function := name "(" *("," expr) ")"
var := "$" varname
varname := msgvar / sysvar
msgvar := name
sysvar := "$" name
name := alpha *(alnum)
constant := string / number
string := simpstr / tplstr ; tplstr will be implemented in next phase
simpstr := "'" *char "'" ; use your imagination for char ;)
tplstr := '"' template '"' ; not initially implemented
number := ["-"] 1*digit ; 0nn = octal, 0xnn = hex, nn = decimal
cmp_op := "==" / "!=" / "<>" / "<" / ">" / "<=" / ">=" / "contains" / "startswith"
digit := %x30-39
alpha := "a" ... "z" # all letters
alnum :* alpha / digit / "_"
Some samples of RainerScript:
define function IsLinux
begin
if $environ contains "linux" then return true else return false
end
load if IsLinux() 'imklog.so' params name='klog' endparams /* load klog under linux only */
run if IsLinux() input 'klog'
load 'ommysql.so'
if $message contains "error" then
action
type='ommysql.so', queue.mode='disk', queue.highwatermark = 300,
action.dbname='events', action.dbuser='uid',
[?action.template='templatename'?] or [?action.sql='insert into table... values('+$facility+','+$severity+...?]
endaction
... or ...
define action writeMySQL
type='ommysql.so', queue.mode='disk', queue.highwatermark = 300,
action.dbname='events', action.dbuser='uid',
[?action.template='templatename'?] or [?action.sql='insert into table... values('+$facility+','+$severity+...?]
endaction
if $message contains "error" then action writeMySQL
ALTERNATE APPROACH
define function IsLinux(
if $environ contains "linux" then return true else return false
)
load if IsLinux() 'imklog.so' params name='klog' endparams /* load klog under linux only */
run if IsLinux() input 'klog'
load 'ommysql.so'
if $message contains "error" then
action(
type='ommysql.so', queue.mode='disk', queue.highwatermark = 300,
action.dbname='events', action.dbuser='uid',
[?action.template='templatename'?] or [?action.sql='insert into table... values('+$facility+','+$severity+...?]
)
... or ...
define action writeMySQL(
type='ommysql.so', queue.mode='disk', queue.highwatermark = 300,
action.dbname='events', action.dbuser='uid',
[?action.template='templatename'?] or [?action.sql='insert into table... values('+$facility+','+$severity+...?]
)
if $message contains "error" then action writeMySQL(action.dbname='differentDB')
Some samples of RainerScript:
define function IsLinux
begin
if $environ contains "linux" then return true else return false
end
load if IsLinux() 'imklog.so' params name='klog' endparams /* load klog under linux only */
run if IsLinux() input 'klog'
load 'ommysql.so'
if $message contains "error" then
action
type='ommysql.so', queue.mode='disk', queue.highwatermark = 300,
action.dbname='events', action.dbuser='uid',
+ [?action.template='templatename'?] or [?action.sql='insert into
+table... values('&$facility&','&$severity&...?]
endaction
... or ...
define action writeMySQL
type='ommysql.so', queue.mode='disk', queue.highwatermark = 300,
action.dbname='events', action.dbuser='uid',
[?action.template='templatename'?] or [?action.sql='insert into table... values(' & $facility & ',' & $severity &...?]
endaction
if $message contains "error" then action writeMySQL
ALTERNATE APPROACH
define function IsLinux(
if $environ contains "linux" then return true else return false
)
load if IsLinux() 'imklog.so' params name='klog' endparams /* load klog under linux only */
run if IsLinux() input 'klog'
load 'ommysql.so'
if $message contains "error" then
action(
type='ommysql.so', queue.mode='disk', queue.highwatermark = 300,
action.dbname='events', action.dbuser='uid',
+ [?action.template='templatename'?] or [?action.sql='insert into
+table... values('&$facility&','&$severity&...?]
)
... or ...
define action writeMySQL(
type='ommysql.so', queue.mode='disk', queue.highwatermark = 300,
action.dbname='events', action.dbuser='uid',
+ [?action.template='templatename'?] or [?action.sql='insert into
+table... values('&$facility&','&$severity&...?]
)
if $message contains "error" then action writeMySQL(action.dbname='differentDB')
[rsyslog.conf overview] [manual index] [rsyslog site]
This documentation is part of the rsyslog diff --git a/expr.c b/expr.c index 156621c1..03ced285 100644 --- a/expr.c +++ b/expr.c @@ -211,8 +211,8 @@ val(expr_t *pThis, ctok_t *tok) /* *(("+" / "-") term) part */ CHKiRet(ctok.GetToken(tok, &pToken)); - while(pToken->tok == ctok_PLUS || pToken->tok == ctok_MINUS) { - dbgoprint((obj_t*) pThis, "+/-\n"); + while(pToken->tok == ctok_PLUS || pToken->tok == ctok_MINUS || pToken->tok == ctok_STRADD) { + dbgoprint((obj_t*) pThis, "+/-/&\n"); CHKiRet(term(pThis, tok)); CHKiRet(vmprg.AddVarOperation(pThis->pVmprg, (opcode_t) pToken->tok, NULL)); /* add to program */ CHKiRet(ctok_token.Destruct(&pToken)); /* no longer needed */ diff --git a/stringbuf.c b/stringbuf.c index 80f1bb97..ecd70113 100755 --- a/stringbuf.c +++ b/stringbuf.c @@ -236,6 +236,15 @@ rsRetVal rsCStrAppendStr(cstr_t *pThis, uchar* psz) } +/* append the contents of one cstr_t object to another + * rgerhards, 2008-02-25 + */ +rsRetVal rsCStrAppendCStr(cstr_t *pThis, cstr_t *pstrAppend) +{ + return rsCStrAppendStrWithLen(pThis, pstrAppend->pBuf, pstrAppend->iStrLen); +} + + rsRetVal rsCStrAppendInt(cstr_t *pThis, long i) { DEFiRet; diff --git a/stringbuf.h b/stringbuf.h index d8e72999..c3db2486 100755 --- a/stringbuf.h +++ b/stringbuf.h @@ -140,6 +140,7 @@ int rsCStrSzStrStartsWithCStr(cstr_t *pCS1, uchar *psz, size_t iLenSz); int rsCStrSzStrMatchRegex(cstr_t *pCS1, uchar *psz); rsRetVal rsCStrConvertToNumber(cstr_t *pStr, number_t *pNumber); rsRetVal rsCStrConvertToBool(cstr_t *pStr, number_t *pBool); +rsRetVal rsCStrAppendCStr(cstr_t *pThis, cstr_t *pstrAppend); /* now come inline-like functions */ #ifdef NDEBUG diff --git a/vm.c b/vm.c index c85df45f..d0b5e141 100644 --- a/vm.c +++ b/vm.c @@ -205,6 +205,21 @@ ENDop(CMP_CONTAINS) /* end comare operations that work on strings, only */ +BEGINop(STRADD) /* remember to set the instruction also in the ENDop macro! */ + var_t *operand1; + var_t *operand2; +CODESTARTop(STRADD) + vmstk.PopString(pThis->pStk, &operand2); + vmstk.PopString(pThis->pStk, &operand1); + + CHKiRet(rsCStrAppendCStr(operand1->val.pStr, operand2->val.pStr)); + + /* we have a result, so let's push it */ + vmstk.Push(pThis->pStk, operand1); + var.Destruct(&operand2); /* no longer needed */ +finalize_it: +ENDop(STRADD) + BEGINop(NOT) /* remember to set the instruction also in the ENDop macro! */ var_t *operand; CODESTARTop(NOT) @@ -332,6 +347,7 @@ execProg(vm_t *pThis, vmprg_t *pProg) doOP(PUSHCONSTANT); doOP(PUSHMSGVAR); doOP(PUSHSYSVAR); + doOP(STRADD); doOP(PLUS); doOP(MINUS); doOP(TIMES); diff --git a/vmop.c b/vmop.c index 56112be5..8e3ae90c 100644 --- a/vmop.c +++ b/vmop.c @@ -173,6 +173,9 @@ vmopOpcode2Str(vmop_t *pThis, uchar **ppName) case opcode_UNARY_MINUS: *ppName = (uchar*) "UNARY_MINUS"; break; + case opcode_STRADD: + *ppName = (uchar*) "STRADD"; + break; default: *ppName = (uchar*) "INVALID opcode"; break; diff --git a/vmop.h b/vmop.h index 70e166e3..804da5be 100644 --- a/vmop.h +++ b/vmop.h @@ -32,6 +32,7 @@ typedef enum { /* do NOT start at 0 to detect uninitialized types after calloc( */ opcode_OR = ctok_OR, opcode_AND = ctok_AND, + opcode_STRADD= ctok_STRADD, opcode_PLUS = ctok_PLUS, opcode_MINUS = ctok_MINUS, opcode_TIMES = ctok_TIMES, /* "*" */ -- cgit v1.2.3