summaryrefslogtreecommitdiff
path: root/grammar
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2013-04-10 12:24:34 +0200
committerMichael Biebl <biebl@debian.org>2013-04-10 12:24:34 +0200
commit79b9293acbb763ad949ed7878f138f424dfa85ac (patch)
tree141c5e0b64fdfbee653542e8a0a3f6d7e3c94671 /grammar
parentd7c2f609d30d5e4d2c69dd2dc7305bd8ec5736ec (diff)
downloadrsyslog-79b9293acbb763ad949ed7878f138f424dfa85ac.tar.gz
Imported Upstream version 7.3.10upstream/7.3.10
Diffstat (limited to 'grammar')
-rw-r--r--grammar/rainerscript.c291
-rw-r--r--grammar/rainerscript.h3
2 files changed, 231 insertions, 63 deletions
diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c
index 8ef7429..89cf946 100644
--- a/grammar/rainerscript.c
+++ b/grammar/rainerscript.c
@@ -2,7 +2,7 @@
*
* Module begun 2011-07-01 by Rainer Gerhards
*
- * Copyright 2011-2012 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2011-2013 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
@@ -1228,6 +1228,96 @@ finalize_it:
RETiRet;
}
+static inline void
+doFunc_re_extract(struct cnffunc *func, struct var *ret, void* usrptr)
+{
+ size_t submatchnbr;
+ short matchnbr;
+ regmatch_t pmatch[50];
+ int bMustFree;
+ es_str_t *estr;
+ char *str;
+ struct var r[CNFFUNC_MAX_ARGS];
+ int iLenBuf;
+ unsigned iOffs;
+ short iTry = 0;
+ uchar bFound = 0;
+ iOffs = 0;
+ sbool bHadNoMatch = 0;
+
+ cnfexprEval(func->expr[0], &r[0], usrptr);
+ /* search string is already part of the compiled regex, so we don't
+ * need it here!
+ */
+ cnfexprEval(func->expr[2], &r[2], usrptr);
+ cnfexprEval(func->expr[3], &r[3], usrptr);
+ str = (char*) var2CString(&r[0], &bMustFree);
+ matchnbr = (short) var2Number(&r[2], NULL);
+ submatchnbr = (size_t) var2Number(&r[3], NULL);
+ if(submatchnbr > sizeof(pmatch)/sizeof(regmatch_t)) {
+ DBGPRINTF("re_extract() submatch %d is too large\n", submatchnbr);
+ bHadNoMatch = 1;
+ goto finalize_it;
+ }
+
+ /* first see if we find a match, iterating through the series of
+ * potential matches over the string.
+ */
+ while(!bFound) {
+ int iREstat;
+ iREstat = regexp.regexec(func->funcdata, (char*)(str + iOffs),
+ submatchnbr+1, pmatch, 0);
+ dbgprintf("re_extract: regexec return is %d\n", iREstat);
+ if(iREstat == 0) {
+ if(pmatch[0].rm_so == -1) {
+ dbgprintf("oops ... start offset of successful regexec is -1\n");
+ break;
+ }
+ if(iTry == matchnbr) {
+ bFound = 1;
+ } else {
+ dbgprintf("re_extract: regex found at offset %d, new offset %d, tries %d\n",
+ iOffs, (int) (iOffs + pmatch[0].rm_eo), iTry);
+ iOffs += pmatch[0].rm_eo;
+ ++iTry;
+ }
+ } else {
+ break;
+ }
+ }
+ dbgprintf("re_extract: regex: end search, found %d\n", bFound);
+ if(!bFound) {
+ bHadNoMatch = 1;
+ goto finalize_it;
+ } else {
+ /* Match- but did it match the one we wanted? */
+ /* we got no match! */
+ if(pmatch[submatchnbr].rm_so == -1) {
+ bHadNoMatch = 1;
+ goto finalize_it;
+ }
+ /* OK, we have a usable match - we now need to malloc pB */
+ iLenBuf = pmatch[submatchnbr].rm_eo - pmatch[submatchnbr].rm_so;
+ estr = es_newStrFromBuf(str + iOffs + pmatch[submatchnbr].rm_so,
+ iLenBuf);
+ }
+
+ if(bMustFree) free(str);
+ if(r[0].datatype == 'S') es_deleteStr(r[0].d.estr);
+ if(r[2].datatype == 'S') es_deleteStr(r[2].d.estr);
+ if(r[3].datatype == 'S') es_deleteStr(r[3].d.estr);
+finalize_it:
+ if(bHadNoMatch) {
+ cnfexprEval(func->expr[4], &r[4], usrptr);
+ estr = var2String(&r[4], &bMustFree);
+ if(r[4].datatype == 'S') es_deleteStr(r[4].d.estr);
+ }
+ ret->datatype = 'S';
+ ret->d.estr = estr;
+ return;
+}
+
+
/* Perform a function call. This has been moved out of cnfExprEval in order
* to keep the code small and easier to maintain.
*/
@@ -1331,6 +1421,9 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr)
if(bMustFree) free(str);
if(r[0].datatype == 'S') es_deleteStr(r[0].d.estr);
break;
+ case CNFFUNC_RE_EXTRACT:
+ doFunc_re_extract(func, ret, usrptr);
+ break;
case CNFFUNC_FIELD:
cnfexprEval(func->expr[0], &r[0], usrptr);
cnfexprEval(func->expr[1], &r[1], usrptr);
@@ -1908,6 +2001,7 @@ cnffuncDestruct(struct cnffunc *func)
/* some functions require special destruction */
switch(func->fID) {
case CNFFUNC_RE_MATCH:
+ case CNFFUNC_RE_EXTRACT:
if(func->funcdata != NULL)
regexp.regfree(func->funcdata);
break;
@@ -2158,31 +2252,33 @@ cnfexprPrint(struct cnfexpr *expr, int indent)
break;
}
}
+/* print only the given stmt
+ * if "subtree" equals 1, the full statement subtree is printed, else
+ * really only the statement.
+ */
void
-cnfstmtPrint(struct cnfstmt *root, int indent)
+cnfstmtPrintOnly(struct cnfstmt *stmt, int indent, sbool subtree)
{
- struct cnfstmt *stmt;
char *cstr;
- //dbgprintf("stmt %p, indent %d, type '%c'\n", expr, indent, expr->nodetype);
- for(stmt = root ; stmt != NULL ; stmt = stmt->next) {
- switch(stmt->nodetype) {
- case S_NOP:
- doIndent(indent); dbgprintf("NOP\n");
- break;
- case S_STOP:
- doIndent(indent); dbgprintf("STOP\n");
- break;
- case S_CALL:
- cstr = es_str2cstr(stmt->d.s_call.name, NULL);
- doIndent(indent); dbgprintf("CALL [%s]\n", cstr);
- free(cstr);
- break;
- case S_ACT:
- doIndent(indent); dbgprintf("ACTION %p [%s]\n", stmt->d.act, stmt->printable);
- break;
- case S_IF:
- doIndent(indent); dbgprintf("IF\n");
- cnfexprPrint(stmt->d.s_if.expr, indent+1);
+ switch(stmt->nodetype) {
+ case S_NOP:
+ doIndent(indent); dbgprintf("NOP\n");
+ break;
+ case S_STOP:
+ doIndent(indent); dbgprintf("STOP\n");
+ break;
+ case S_CALL:
+ cstr = es_str2cstr(stmt->d.s_call.name, NULL);
+ doIndent(indent); dbgprintf("CALL [%s]\n", cstr);
+ free(cstr);
+ break;
+ case S_ACT:
+ doIndent(indent); dbgprintf("ACTION %p [%s]\n", stmt->d.act, stmt->printable);
+ break;
+ case S_IF:
+ doIndent(indent); dbgprintf("IF\n");
+ cnfexprPrint(stmt->d.s_if.expr, indent+1);
+ if(subtree) {
doIndent(indent); dbgprintf("THEN\n");
cnfstmtPrint(stmt->d.s_if.t_then, indent+1);
if(stmt->d.s_if.t_else != NULL) {
@@ -2190,54 +2286,67 @@ cnfstmtPrint(struct cnfstmt *root, int indent)
cnfstmtPrint(stmt->d.s_if.t_else, indent+1);
}
doIndent(indent); dbgprintf("END IF\n");
- break;
- case S_SET:
- doIndent(indent); dbgprintf("SET %s =\n",
- stmt->d.s_set.varname);
- cnfexprPrint(stmt->d.s_set.expr, indent+1);
- doIndent(indent); dbgprintf("END SET\n");
- break;
- case S_UNSET:
- doIndent(indent); dbgprintf("UNSET %s\n",
- stmt->d.s_unset.varname);
- break;
- case S_PRIFILT:
- doIndent(indent); dbgprintf("PRIFILT '%s'\n", stmt->printable);
- pmaskPrint(stmt->d.s_prifilt.pmask, indent);
+ }
+ break;
+ case S_SET:
+ doIndent(indent); dbgprintf("SET %s =\n",
+ stmt->d.s_set.varname);
+ cnfexprPrint(stmt->d.s_set.expr, indent+1);
+ doIndent(indent); dbgprintf("END SET\n");
+ break;
+ case S_UNSET:
+ doIndent(indent); dbgprintf("UNSET %s\n",
+ stmt->d.s_unset.varname);
+ break;
+ case S_PRIFILT:
+ doIndent(indent); dbgprintf("PRIFILT '%s'\n", stmt->printable);
+ pmaskPrint(stmt->d.s_prifilt.pmask, indent);
+ if(subtree) {
cnfstmtPrint(stmt->d.s_prifilt.t_then, indent+1);
if(stmt->d.s_prifilt.t_else != NULL) {
doIndent(indent); dbgprintf("ELSE\n");
cnfstmtPrint(stmt->d.s_prifilt.t_else, indent+1);
}
doIndent(indent); dbgprintf("END PRIFILT\n");
- break;
- case S_PROPFILT:
- doIndent(indent); dbgprintf("PROPFILT\n");
- doIndent(indent); dbgprintf("\tProperty.: '%s'\n",
- propIDToName(stmt->d.s_propfilt.propID));
- if(stmt->d.s_propfilt.propName != NULL) {
- 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));
- }
+ }
+ break;
+ case S_PROPFILT:
+ doIndent(indent); dbgprintf("PROPFILT\n");
+ doIndent(indent); dbgprintf("\tProperty.: '%s'\n",
+ propIDToName(stmt->d.s_propfilt.propID));
+ if(stmt->d.s_propfilt.propName != NULL) {
+ 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));
+ }
+ if(subtree) {
doIndent(indent); dbgprintf("THEN\n");
cnfstmtPrint(stmt->d.s_propfilt.t_then, indent+1);
doIndent(indent); dbgprintf("END PROPFILT\n");
- break;
- default:
- dbgprintf("error: unknown stmt type %u\n",
- (unsigned) stmt->nodetype);
- break;
}
+ break;
+ default:
+ dbgprintf("error: unknown stmt type %u\n",
+ (unsigned) stmt->nodetype);
+ break;
+ }
+}
+void
+cnfstmtPrint(struct cnfstmt *root, int indent)
+{
+ struct cnfstmt *stmt;
+ //dbgprintf("stmt %p, indent %d, type '%c'\n", expr, indent, expr->nodetype);
+ for(stmt = root ; stmt != NULL ; stmt = stmt->next) {
+ cnfstmtPrintOnly(stmt, indent, 1);
}
}
@@ -2988,7 +3097,6 @@ cnfstmtOptimize(struct cnfstmt *root)
struct cnfstmt *stmt;
if(root == NULL) goto done;
for(stmt = root ; stmt != NULL ; stmt = stmt->next) {
-dbgprintf("RRRR: stmtOptimize: stmt %p, nodetype %u\n", stmt, stmt->nodetype);
switch(stmt->nodetype) {
case S_IF:
cnfstmtOptimizeIf(stmt);
@@ -3088,6 +3196,13 @@ funcName2ID(es_str_t *fname, unsigned short nParams)
return CNFFUNC_INVALID;
}
return CNFFUNC_RE_MATCH;
+ } else if(!es_strbufcmp(fname, (unsigned char*)"re_extract", sizeof("re_extract") - 1)) {
+ if(nParams != 5) {
+ parser_errmsg("number of parameters for re_extract() must be five "
+ "but is %d.", nParams);
+ return CNFFUNC_INVALID;
+ }
+ return CNFFUNC_RE_EXTRACT;
} else if(!es_strbufcmp(fname, (unsigned char*)"field", sizeof("field") - 1)) {
if(nParams != 3) {
parser_errmsg("number of parameters for field() must be three "
@@ -3118,7 +3233,7 @@ initFunc_re_match(struct cnffunc *func)
func->funcdata = NULL;
if(func->expr[1]->nodetype != 'S') {
- parser_errmsg("param 2 of re_match() must be a constant string");
+ parser_errmsg("param 2 of re_match/extract() must be a constant string");
FINALIZE;
}
@@ -3196,6 +3311,7 @@ cnffuncNew(es_str_t *fname, struct cnffparamlst* paramlst)
/* some functions require special initialization */
switch(func->fID) {
case CNFFUNC_RE_MATCH:
+ case CNFFUNC_RE_EXTRACT:
/* need to compile the regexp in param 2, so this MUST be a constant */
initFunc_re_match(func);
break;
@@ -3520,3 +3636,52 @@ unescapeStr(uchar *s, int len)
s[iDst] = '\0';
}
}
+
+char *
+tokenval2str(int tok)
+{
+ if(tok < 256) return "";
+ switch(tok) {
+ case NAME: return "NAME";
+ case FUNC: return "FUNC";
+ case BEGINOBJ: return "BEGINOBJ";
+ case ENDOBJ: return "ENDOBJ";
+ case BEGIN_ACTION: return "BEGIN_ACTION";
+ case BEGIN_PROPERTY: return "BEGIN_PROPERTY";
+ case BEGIN_CONSTANT: return "BEGIN_CONSTANT";
+ case BEGIN_TPL: return "BEGIN_TPL";
+ case BEGIN_RULESET: return "BEGIN_RULESET";
+ case STOP: return "STOP";
+ case SET: return "SET";
+ case UNSET: return "UNSET";
+ case CONTINUE: return "CONTINUE";
+ case CALL: return "CALL";
+ case LEGACY_ACTION: return "LEGACY_ACTION";
+ case LEGACY_RULESET: return "LEGACY_RULESET";
+ case PRIFILT: return "PRIFILT";
+ case PROPFILT: return "PROPFILT";
+ case BSD_TAG_SELECTOR: return "BSD_TAG_SELECTOR";
+ case BSD_HOST_SELECTOR: return "BSD_HOST_SELECTOR";
+ case IF: return "IF";
+ case THEN: return "THEN";
+ case ELSE: return "ELSE";
+ case OR: return "OR";
+ case AND: return "AND";
+ case NOT: return "NOT";
+ case VAR: return "VAR";
+ case STRING: return "STRING";
+ case NUMBER: return "NUMBER";
+ case CMP_EQ: return "CMP_EQ";
+ case CMP_NE: return "CMP_NE";
+ case CMP_LE: return "CMP_LE";
+ case CMP_GE: return "CMP_GE";
+ case CMP_LT: return "CMP_LT";
+ case CMP_GT: return "CMP_GT";
+ case CMP_CONTAINS: return "CMP_CONTAINS";
+ case CMP_CONTAINSI: return "CMP_CONTAINSI";
+ case CMP_STARTSWITH: return "CMP_STARTSWITH";
+ case CMP_STARTSWITHI: return "CMP_STARTSWITHI";
+ case UMINUS: return "UMINUS";
+ default: return "UNKNOWN TOKEN";
+ }
+}
diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h
index 59ce53f..31b2eb9 100644
--- a/grammar/rainerscript.h
+++ b/grammar/rainerscript.h
@@ -226,6 +226,7 @@ enum cnffuncid {
CNFFUNC_CSTR,
CNFFUNC_CNUM,
CNFFUNC_RE_MATCH,
+ CNFFUNC_RE_EXTRACT,
CNFFUNC_FIELD,
CNFFUNC_PRIFILT
};
@@ -317,6 +318,7 @@ int cnfparamvalsIsSet(struct cnfparamblk *params, struct cnfparamvals *vals);
void varDelete(struct var *v);
void cnfparamvalsDestruct(struct cnfparamvals *paramvals, struct cnfparamblk *blk);
struct cnfstmt * cnfstmtNew(unsigned s_type);
+void cnfstmtPrintOnly(struct cnfstmt *stmt, int indent, sbool subtree);
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);
@@ -338,6 +340,7 @@ void cnfarrayContentDestruct(struct cnfarray *ar);
char* getFIOPName(unsigned iFIOP);
rsRetVal initRainerscript(void);
void unescapeStr(uchar *s, int len);
+char * tokenval2str(int tok);
/* debug helper */
void cstrPrint(char *text, es_str_t *estr);