summaryrefslogtreecommitdiffstats
path: root/grammar/rainerscript.c
diff options
context:
space:
mode:
Diffstat (limited to 'grammar/rainerscript.c')
-rw-r--r--grammar/rainerscript.c604
1 files changed, 448 insertions, 156 deletions
diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c
index a5cc10c2..30600ea3 100644
--- a/grammar/rainerscript.c
+++ b/grammar/rainerscript.c
@@ -2,7 +2,7 @@
*
* Module begun 2011-07-01 by Rainer Gerhards
*
- * Copyright 2011 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2011-2012 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
@@ -37,10 +37,48 @@
#include <libestr.h>
#include "rsyslog.h"
#include "rainerscript.h"
+#include "conf.h"
#include "parserif.h"
+#include "rsconf.h"
#include "grammar.h"
#include "queue.h"
#include "srUtils.h"
+#include "regexp.h"
+#include "obj.h"
+
+DEFobjCurrIf(obj)
+DEFobjCurrIf(regexp)
+
+char*
+getFIOPName(unsigned iFIOP)
+{
+ char *pRet;
+ switch(iFIOP) {
+ case FIOP_CONTAINS:
+ pRet = "contains";
+ break;
+ case FIOP_ISEQUAL:
+ pRet = "isequal";
+ break;
+ case FIOP_STARTSWITH:
+ pRet = "startswith";
+ break;
+ case FIOP_REGEX:
+ pRet = "regex";
+ break;
+ case FIOP_EREREGEX:
+ pRet = "ereregex";
+ break;
+ case FIOP_ISEMPTY:
+ pRet = "isempty";
+ break;
+ default:
+ pRet = "NOP";
+ break;
+ }
+ return pRet;
+}
+
void
readConfFile(FILE *fp, es_str_t **str)
@@ -93,6 +131,80 @@ readConfFile(FILE *fp, es_str_t **str)
es_addChar(str, '\0');
}
+struct objlst*
+objlstNew(struct cnfobj *o)
+{
+ struct objlst *lst;
+
+ if((lst = malloc(sizeof(struct objlst))) != NULL) {
+ lst->next = NULL;
+ lst->obj = o;
+ }
+cnfobjPrint(o);
+
+ return lst;
+}
+
+/* add object to end of object list, always returns pointer to root object */
+struct objlst*
+objlstAdd(struct objlst *root, struct cnfobj *o)
+{
+ struct objlst *l;
+ struct objlst *newl;
+
+ newl = objlstNew(o);
+ if(root == 0) {
+ root = newl;
+ } else { /* find last, linear search ok, as only during config phase */
+ for(l = root ; l->next != NULL ; l = l->next)
+ ;
+ l->next = newl;
+ }
+ 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)
+{
+ struct objlst *toDel;
+
+ while(lst != NULL) {
+ toDel = lst;
+ lst = lst->next;
+ cnfobjDestruct(toDel->obj);
+ free(toDel);
+ }
+}
+
+void
+objlstPrint(struct objlst *lst)
+{
+ dbgprintf("objlst %p:\n", lst);
+ while(lst != NULL) {
+ cnfobjPrint(lst->obj);
+ lst = lst->next;
+ }
+}
+
struct nvlst*
nvlstNew(es_str_t *name, es_str_t *value)
{
@@ -576,6 +688,7 @@ cnfobjNew(enum cnfobjType objType, struct nvlst *lst)
nvlstChkDupes(lst);
o->objType = objType;
o->nvlst = lst;
+ o->subobjs = NULL;
}
return o;
@@ -586,6 +699,7 @@ cnfobjDestruct(struct cnfobj *o)
{
if(o != NULL) {
nvlstDestruct(o->nvlst);
+ objlstDestruct(o->subobjs);
free(o);
}
}
@@ -598,117 +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) {
- //dbgprintf("reversing: %s\n", actlst->data.legActLine);
- 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)
{
@@ -749,8 +752,7 @@ var2Number(struct var *r, int *bSuccess)
return n;
}
-/* ensure that retval is a string; if string is no number,
- * emit error message and set number to 0.
+/* ensure that retval is a string
*/
static inline es_str_t *
var2String(struct var *r, int *bMustFree)
@@ -774,6 +776,7 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr)
int bMustFree;
es_str_t *estr;
char *str;
+ int retval;
struct var r[CNFFUNC_MAX_ARGS];
dbgprintf("rainerscript: executing function id %d\n", func->fID);
@@ -816,6 +819,7 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr)
es_tolower(estr);
ret->datatype = 'S';
ret->d.estr = estr;
+ if(r[0].datatype == 'S') es_deleteStr(r[0].d.estr);
break;
case CNFFUNC_CSTR:
cnfexprEval(func->expr[0], &r[0], usrptr);
@@ -824,6 +828,7 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr)
estr = es_strdup(estr);
ret->datatype = 'S';
ret->d.estr = estr;
+ if(r[0].datatype == 'S') es_deleteStr(r[0].d.estr);
break;
case CNFFUNC_CNUM:
if(func->expr[0]->nodetype == 'N') {
@@ -838,6 +843,24 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr)
}
ret->datatype = 'N';
break;
+ case CNFFUNC_RE_MATCH:
+ cnfexprEval(func->expr[0], &r[0], usrptr);
+ estr = var2String(&r[0], &bMustFree);
+ str = es_str2cstr(estr, NULL);
+ retval = regexp.regexec(func->funcdata, str, 0, NULL, 0);
+ if(retval == 0)
+ ret->d.n = 1;
+ else {
+ ret->d.n = 0;
+ if(retval != REG_NOMATCH) {
+ DBGPRINTF("re_match: regexec returned error %d\n", retval);
+ }
+ }
+ ret->datatype = 'N';
+ if(bMustFree) es_deleteStr(estr);
+ free(str);
+ if(r[0].datatype == 'S') es_deleteStr(r[0].d.estr);
+ break;
default:
if(Debug) {
fname = es_str2cstr(func->fname, NULL);
@@ -891,7 +914,7 @@ cnfexprEval(struct cnfexpr *expr, struct var *ret, void* usrptr)
int bMustFree, bMustFree2;
long long n_r, n_l;
- //dbgprintf("eval expr %p, type '%c'(%u)\n", expr, expr->nodetype, expr->nodetype);
+ dbgprintf("eval expr %p, type '%c'(%u)\n", expr, expr->nodetype, expr->nodetype);
switch(expr->nodetype) {
/* note: comparison operations are extremely similar. The code can be copyied, only
* places flagged with "CMP" need to be changed.
@@ -1199,6 +1222,78 @@ cnfexprEval(struct cnfexpr *expr, struct var *ret, void* usrptr)
}
}
+//---------------------------------------------------------
+
+static inline void
+cnffuncDestruct(struct cnffunc *func)
+{
+ unsigned short i;
+
+ for(i = 0 ; i < func->nParams ; ++i) {
+ cnfexprDestruct(func->expr[i]);
+ }
+ /* some functions require special destruction */
+ switch(func->fID) {
+ case CNFFUNC_RE_MATCH:
+ regexp.regfree(func->funcdata);
+ free(func->funcdata);
+ free(func->fname);
+ break;
+ default:break;
+ }
+}
+
+/* Destruct an expression and all sub-expressions contained in it.
+ */
+void
+cnfexprDestruct(struct cnfexpr *expr)
+{
+
+ dbgprintf("cnfexprDestruct expr %p, type '%c'(%u)\n", expr, expr->nodetype, expr->nodetype);
+ switch(expr->nodetype) {
+ case CMP_NE:
+ case CMP_EQ:
+ case CMP_LE:
+ case CMP_GE:
+ case CMP_LT:
+ case CMP_GT:
+ case CMP_STARTSWITH:
+ case CMP_STARTSWITHI:
+ case CMP_CONTAINS:
+ case CMP_CONTAINSI:
+ case OR:
+ case AND:
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%': /* binary */
+ cnfexprDestruct(expr->l);
+ cnfexprDestruct(expr->r);
+ break;
+ case NOT:
+ case 'M': /* unary */
+ cnfexprDestruct(expr->r);
+ break;
+ case 'N':
+ break;
+ case 'S':
+ es_deleteStr(((struct cnfstringval*)expr)->estr);
+ break;
+ case 'V':
+ free(((struct cnfvar*)expr)->name);
+ break;
+ case 'F':
+ cnffuncDestruct((struct cnffunc*)expr);
+ break;
+ default:break;
+ }
+ free(expr);
+}
+
+//---- END
+
+
/* Evaluate an expression as a bool. This is added because expressions are
* mostly used inside filters, and so this function is quite common and
* important.
@@ -1344,6 +1439,68 @@ cnfexprPrint(struct cnfexpr *expr, int indent)
break;
}
}
+void
+cnfstmtPrint(struct cnfstmt *root, int indent)
+{
+ struct cnfstmt *stmt;
+ //dbgprintf("stmt %p, indent %d, type '%c'\n", expr, indent, expr->nodetype);
+ for(stmt = root ; stmt != NULL ; stmt = stmt->next) {
+ switch(stmt->nodetype) {
+ case S_NOP:
+ doIndent(indent); dbgprintf("NOP\n");
+ break;
+ case S_STOP:
+ doIndent(indent); dbgprintf("STOP\n");
+ break;
+ case S_ACT:
+ doIndent(indent); dbgprintf("ACTION %p (%s)\n", stmt->d.act, stmt->printable);
+ break;
+ case S_IF:
+ doIndent(indent); dbgprintf("IF\n");
+ cnfexprPrint(stmt->d.s_if.expr, indent+1);
+ doIndent(indent); dbgprintf("THEN\n");
+ cnfstmtPrint(stmt->d.s_if.t_then, indent+1);
+ if(stmt->d.s_if.t_else != NULL) {
+ doIndent(indent); dbgprintf("ELSE\n");
+ cnfstmtPrint(stmt->d.s_if.t_else, indent+1);
+ }
+ doIndent(indent); dbgprintf("END IF\n");
+ break;
+ case S_PRIFILT:
+ doIndent(indent); dbgprintf("PRIFILT '%s'\n", stmt->printable);
+ cnfstmtPrint(stmt->d.s_prifilt.t_then, indent+1);
+ doIndent(indent); dbgprintf("END PRIFILT\n");
+ break;
+ case S_PROPFILT:
+ doIndent(indent); dbgprintf("PROPFILT\n");
+ doIndent(indent); dbgprintf("\tProperty.: '%s'\n",
+ propIDToName(stmt->d.s_propfilt.propID));
+ if(stmt->d.s_propfilt.propName != NULL) {
+ char *cstr;
+ cstr = es_str2cstr(stmt->d.s_propfilt.propName, NULL);
+ doIndent(indent);
+ dbgprintf("\tCEE-Prop.: '%s'\n", cstr);
+ free(cstr);
+ }
+ doIndent(indent); dbgprintf("\tOperation: ");
+ if(stmt->d.s_propfilt.isNegated)
+ dbgprintf("NOT ");
+ dbgprintf("'%s'\n", getFIOPName(stmt->d.s_propfilt.operation));
+ if(stmt->d.s_propfilt.pCSCompValue != NULL) {
+ doIndent(indent); dbgprintf("\tValue....: '%s'\n",
+ rsCStrGetSzStrNoNULL(stmt->d.s_propfilt.pCSCompValue));
+ }
+ doIndent(indent); dbgprintf("THEN\n");
+ cnfstmtPrint(stmt->d.s_propfilt.t_then, indent+1);
+ doIndent(indent); dbgprintf("END PROPFILT\n");
+ break;
+ default:
+ dbgprintf("error: unknown stmt type %u\n",
+ (unsigned) stmt->nodetype);
+ break;
+ }
+ }
+}
struct cnfnumval*
cnfnumvalNew(long long val)
@@ -1367,6 +1524,7 @@ cnfstringvalNew(es_str_t *estr)
return strval;
}
+
struct cnfvar*
cnfvarNew(char *name)
{
@@ -1378,61 +1536,126 @@ cnfvarNew(char *name)
return var;
}
-struct cnfrule *
-cnfruleNew(enum cnfFiltType filttype, struct cnfactlst *actlst)
+struct cnfstmt *
+cnfstmtNew(unsigned s_type)
{
- struct cnfrule* cnfrule;
- if((cnfrule = malloc(sizeof(struct cnfrule))) != NULL) {
- cnfrule->nodetype = 'R';
- cnfrule->filttype = filttype;
- cnfrule->actlst = cnfactlstReverse(actlst);
+ struct cnfstmt* cnfstmt;
+ if((cnfstmt = malloc(sizeof(struct cnfstmt))) != NULL) {
+ cnfstmt->nodetype = s_type;
+ cnfstmt->printable = NULL;
+ cnfstmt->next = NULL;
}
- return cnfrule;
+ return cnfstmt;
}
void
-cnfrulePrint(struct cnfrule *rule)
+cnfstmtDestruct(struct cnfstmt *root)
{
- dbgprintf("------ start rule %p:\n", rule);
- dbgprintf("%s: ", cnfFiltType2str(rule->filttype));
- switch(rule->filttype) {
- case CNFFILT_NONE:
- break;
- case CNFFILT_PRI:
- case CNFFILT_PROP:
- dbgprintf("%s\n", rule->filt.s);
- break;
- case CNFFILT_SCRIPT:
- dbgprintf("\n");
- cnfexprPrint(rule->filt.expr, 0);
- break;
+ struct cnfstmt *stmt, *todel;
+ for(stmt = root ; stmt != NULL ; ) {
+ switch(stmt->nodetype) {
+ case S_NOP:
+ case S_STOP:
+ break;
+ case S_ACT:
+ actionDestruct(stmt->d.act);
+ break;
+ case S_IF:
+ cnfexprDestruct(stmt->d.s_if.expr);
+ if(stmt->d.s_if.t_then != NULL) {
+ cnfstmtDestruct(stmt->d.s_if.t_then);
+ }
+ if(stmt->d.s_if.t_else != NULL) {
+ cnfstmtDestruct(stmt->d.s_if.t_else);
+ }
+ break;
+ case S_PRIFILT:
+ cnfstmtDestruct(stmt->d.s_prifilt.t_then);
+ break;
+ case S_PROPFILT:
+ if(stmt->d.s_propfilt.propName != NULL)
+ es_deleteStr(stmt->d.s_propfilt.propName);
+ if(stmt->d.s_propfilt.regex_cache != NULL)
+ rsCStrRegexDestruct(&stmt->d.s_propfilt.regex_cache);
+ if(stmt->d.s_propfilt.pCSCompValue != NULL)
+ cstrDestruct(&stmt->d.s_propfilt.pCSCompValue);
+ cnfstmtDestruct(stmt->d.s_propfilt.t_then);
+ break;
+ default:
+ dbgprintf("error: unknown stmt type during destruct %u\n",
+ (unsigned) stmt->nodetype);
+ break;
+ }
+ free(stmt->printable);
+ todel = stmt;
+ stmt = stmt->next;
+ free(todel);
}
- cnfactlstPrint(rule->actlst);
- dbgprintf("------ end rule %p\n", rule);
}
-/* note: the sysline itself was already freed during processing
- * and as such MUST NOT be freed again!
- */
-void
-cnfcfsyslinelstDestruct(struct cnfcfsyslinelst *cfslst)
+struct cnfstmt *
+cnfstmtNewPRIFILT(char *prifilt, struct cnfstmt *t_then)
{
- struct cnfcfsyslinelst *toDel;
- while(cfslst != NULL) {
- toDel = cfslst;
- cfslst = cfslst->next;
- free(toDel);
+ struct cnfstmt* cnfstmt;
+ if((cnfstmt = cnfstmtNew(S_PRIFILT)) != NULL) {
+ cnfstmt->printable = (uchar*)prifilt;
+ cnfstmt->d.s_prifilt.t_then = t_then;
+ DecodePRIFilter((uchar*)prifilt, cnfstmt->d.s_prifilt.pmask);
}
+ return cnfstmt;
}
-void
-cnfruleDestruct(struct cnfrule *rule)
+struct cnfstmt *
+cnfstmtNewPROPFILT(char *propfilt, struct cnfstmt *t_then)
{
- if( rule->filttype == CNFFILT_PRI
- || rule->filttype == CNFFILT_PROP)
- free(rule->filt.s);
- cnfactlstDestruct(rule->actlst);
- free(rule);
+ struct cnfstmt* cnfstmt;
+ if((cnfstmt = cnfstmtNew(S_PROPFILT)) != NULL) {
+ cnfstmt->printable = (uchar*)propfilt;
+ cnfstmt->d.s_propfilt.t_then = t_then;
+ cnfstmt->d.s_propfilt.propName = NULL;
+ cnfstmt->d.s_propfilt.regex_cache = NULL;
+ cnfstmt->d.s_propfilt.pCSCompValue = NULL;
+ DecodePropFilter((uchar*)propfilt, cnfstmt);
+ }
+ return cnfstmt;
+}
+
+struct cnfstmt *
+cnfstmtNewAct(struct nvlst *lst)
+{
+ struct cnfstmt* cnfstmt;
+ if((cnfstmt = cnfstmtNew(S_ACT)) == NULL)
+ goto done;
+ if(actionNewInst(lst, &cnfstmt->d.act) != RS_RET_OK) {
+ // TODO:RS_RET_WARN?
+ parser_errmsg("errors occured in file '%s' around line %d",
+ cnfcurrfn, yylineno);
+ cnfstmt->nodetype = S_NOP; /* disable action! */
+ goto done;
+ }
+ cnfstmt->printable = (uchar*)strdup("action()");
+done: return cnfstmt;
+}
+
+struct cnfstmt *
+cnfstmtNewLegaAct(char *actline)
+{
+ struct cnfstmt* cnfstmt;
+ rsRetVal localRet;
+ if((cnfstmt = cnfstmtNew(S_ACT)) == NULL)
+ goto done;
+ cnfstmt->printable = (uchar*)strdup((char*)actline);
+ localRet = cflineDoAction(loadConf, (uchar**)&actline, &cnfstmt->d.act);
+ if(localRet != RS_RET_OK && localRet != RS_RET_OK_WARN) {
+ parser_errmsg("%s occured in file '%s' around line %d",
+ (localRet == RS_RET_OK_WARN) ? "warnings" : "errors",
+ cnfcurrfn, yylineno);
+ if(localRet != RS_RET_OK_WARN) {
+ cnfstmt->nodetype = S_NOP; /* disable action! */
+ goto done;
+ }
+ }
+done: return cnfstmt;
}
struct cnffparamlst *
@@ -1488,11 +1711,53 @@ funcName2ID(es_str_t *fname, unsigned short nParams)
return CNFFUNC_INVALID;
}
return CNFFUNC_CNUM;
+ } else if(!es_strbufcmp(fname, (unsigned char*)"re_match", sizeof("re_match") - 1)) {
+ if(nParams != 2) {
+ parser_errmsg("number of parameters for re_match() must be two "
+ "but is %d.", nParams);
+ return CNFFUNC_INVALID;
+ }
+ return CNFFUNC_RE_MATCH;
} else {
return CNFFUNC_INVALID;
}
}
+
+static inline rsRetVal
+initFunc_re_match(struct cnffunc *func)
+{
+ rsRetVal localRet;
+ char *regex = NULL;
+ regex_t *re;
+ DEFiRet;
+
+ func->funcdata = NULL;
+ if(func->expr[1]->nodetype != 'S') {
+ parser_errmsg("param 2 of re_match() must be a constant string");
+ FINALIZE;
+ }
+
+ CHKmalloc(re = malloc(sizeof(regex_t)));
+ func->funcdata = re;
+
+ regex = es_str2cstr(((struct cnfstringval*) func->expr[1])->estr, NULL);
+
+ if((localRet = objUse(regexp, LM_REGEXP_FILENAME)) == RS_RET_OK) {
+ if(regexp.regcomp(re, (char*) regex, REG_EXTENDED) != 0) {
+ parser_errmsg("cannot compile regex '%s'", regex);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else { /* regexp object could not be loaded */
+ parser_errmsg("could not load regex support - regex ignored");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+finalize_it:
+ free(regex);
+ RETiRet;
+}
+
struct cnffunc *
cnffuncNew(es_str_t *fname, struct cnffparamlst* paramlst)
{
@@ -1519,6 +1784,14 @@ cnffuncNew(es_str_t *fname, struct cnffparamlst* paramlst)
param = param->next;
free(toDel);
}
+ /* some functions require special initialization */
+ switch(func->fID) {
+ case CNFFUNC_RE_MATCH:
+ /* need to compile the regexp in param 2, so this MUST be a constant */
+ initFunc_re_match(func);
+ break;
+ default:break;
+ }
}
return func;
}
@@ -1616,3 +1889,22 @@ cstrPrint(char *text, es_str_t *estr)
dbgprintf("%s%s", text, str);
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)
+{
+ DEFiRet;
+ CHKiRet(objGetObjInterface(&obj));
+finalize_it:
+ RETiRet;
+}