summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--grammar/lexer.l2
-rw-r--r--grammar/parserif.h1
-rw-r--r--grammar/rainerscript.c121
-rw-r--r--grammar/rainerscript.h5
-rw-r--r--grammar/testdriver.c9
-rw-r--r--plugins/ommongodb/ommongodb.c18
-rw-r--r--runtime/msg.c349
-rw-r--r--runtime/msg.h27
-rw-r--r--runtime/rsconf.c110
-rw-r--r--runtime/rsyslog.h48
-rw-r--r--runtime/ruleset.c32
-rw-r--r--runtime/ruleset.h2
-rw-r--r--runtime/typedefs.h55
-rw-r--r--template.c148
-rw-r--r--template.h6
16 files changed, 357 insertions, 578 deletions
diff --git a/ChangeLog b/ChangeLog
index e3b18b8c..7517d888 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,5 @@
+- bugfix: unset statement always worked on message var, even if local
+ var was given
---------------------------------------------------------------------------
Version 7.5.6 [devel] 2013-10-??
- RainerScript: make use of 64 bit for numbers where available
diff --git a/grammar/lexer.l b/grammar/lexer.l
index 36c23c7d..7fdb68af 100644
--- a/grammar/lexer.l
+++ b/grammar/lexer.l
@@ -129,7 +129,7 @@ int fileno(FILE *stream);
<EXPR>0[0-7]+ | /* octal number */
<EXPR>0x[0-7a-f] | /* hex number, following rule is dec; strtoll handles all! */
<EXPR>([1-9][0-9]*|0) { yylval.n = strtoll(yytext, NULL, 0); return NUMBER; }
-<EXPR>\$[$!./]{0,1}[a-z][!a-z0-9\-_\.]* { yylval.s = strdup(yytext); return VAR; }
+<EXPR>\$[$!./]{0,1}[a-z][!a-z0-9\-_\.]* { yylval.s = strdup(yytext+1); return VAR; }
<EXPR>\'([^'\\]|\\['"\\$bntr]|\\x[0-9a-f][0-9a-f]|\\[0-7][0-7][0-7])*\' {
yytext[yyleng-1] = '\0';
unescapeStr((uchar*)yytext+1, yyleng-2);
diff --git a/grammar/parserif.h b/grammar/parserif.h
index aa271ec4..6c2c1365 100644
--- a/grammar/parserif.h
+++ b/grammar/parserif.h
@@ -19,5 +19,4 @@ void cnfDoScript(struct cnfstmt *script);
void cnfDoCfsysline(char *ln);
void cnfDoBSDTag(char *ln);
void cnfDoBSDHost(char *ln);
-es_str_t *cnfGetVar(char *name, void *usrptr);
#endif
diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c
index a2bed2bf..abf9dd34 100644
--- a/grammar/rainerscript.c
+++ b/grammar/rainerscript.c
@@ -47,6 +47,8 @@
#include "obj.h"
#include "modules.h"
#include "ruleset.h"
+#include "msg.h"
+#include "unicode-helper.h"
DEFobjCurrIf(obj)
DEFobjCurrIf(regexp)
@@ -176,20 +178,8 @@ DecodePropFilter(uchar *pline, struct cnfstmt *stmt)
rsParsDestruct(pPars);
ABORT_FINALIZE(iRet);
}
- iRet = propNameToID(pCSPropName, &stmt->d.s_propfilt.propID);
- if(iRet != RS_RET_OK) {
- parser_errmsg("invalid property name '%s' in filter",
- cstrGetSzStrNoNULL(pCSPropName));
- rsParsDestruct(pPars);
- ABORT_FINALIZE(iRet);
- }
- if(stmt->d.s_propfilt.propID == PROP_CEE) {
- /* in CEE case, we need to preserve the actual property name */
- if((stmt->d.s_propfilt.propName =
- es_newStrFromBuf((char*)cstrGetSzStrNoNULL(pCSPropName)+2, cstrLen(pCSPropName)-2)) == NULL) {
- ABORT_FINALIZE(RS_RET_ERR);
- }
- }
+ CHKiRet(msgPropDescrFill(&stmt->d.s_propfilt.prop, cstrGetSzStrNoNULL(pCSPropName),
+ cstrLen(pCSPropName)));
/* read operation */
iRet = parsDelimCStr(pPars, &pCSCompOp, ',', 1, 1, 1);
@@ -1257,6 +1247,23 @@ var2CString(struct var *r, int *bMustFree)
return cstr;
}
+/* frees struct var members, but not the struct itself. This is because
+ * it usually is allocated on the stack. Callers why dynamically allocate
+ * struct var need to free the struct themselfes!
+ */
+static void
+varFreeMembers(struct var *r)
+{
+ /* Note: we do NOT need to free JSON objects, as we use
+ * json_object_object_get() to obtain the values, which does not
+ * increment the reference count. So json_object_put() [free] is
+ * neither required nor permitted (would free the original object!).
+ * So for the time being the string data type is the only one that
+ * we currently need to free.
+ */
+ if(r->datatype == 'S') es_deleteStr(r->d.estr);
+}
+
static rsRetVal
doExtractFieldByChar(uchar *str, uchar delim, int matchnbr, uchar **resstr)
{
@@ -1424,9 +1431,9 @@ doFunc_re_extract(struct cnffunc *func, struct var *ret, void* usrptr)
finalize_it:
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);
+ varFreeMembers(&r[0]);
+ varFreeMembers(&r[2]);
+ varFreeMembers(&r[3]);
if(bHadNoMatch) {
cnfexprEval(func->expr[4], &r[4], usrptr);
@@ -1495,7 +1502,7 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr)
}
ret->datatype = 'S';
if(bMustFree) es_deleteStr(estr);
- if(r[0].datatype == 'S') es_deleteStr(r[0].d.estr);
+ varFreeMembers(&r[0]);
free(str);
break;
case CNFFUNC_TOLOWER:
@@ -1506,7 +1513,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);
+ varFreeMembers(&r[0]);
break;
case CNFFUNC_CSTR:
cnfexprEval(func->expr[0], &r[0], usrptr);
@@ -1515,7 +1522,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);
+ varFreeMembers(&r[0]);
break;
case CNFFUNC_CNUM:
if(func->expr[0]->nodetype == 'N') {
@@ -1526,7 +1533,7 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr)
} else {
cnfexprEval(func->expr[0], &r[0], usrptr);
ret->d.n = var2Number(&r[0], NULL);
- if(r[0].datatype == 'S') es_deleteStr(r[0].d.estr);
+ varFreeMembers(&r[0]);
}
ret->datatype = 'N';
break;
@@ -1544,7 +1551,7 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr)
}
ret->datatype = 'N';
if(bMustFree) free(str);
- if(r[0].datatype == 'S') es_deleteStr(r[0].d.estr);
+ varFreeMembers(&r[0]);
break;
case CNFFUNC_RE_EXTRACT:
doFunc_re_extract(func, ret, usrptr);
@@ -1577,9 +1584,9 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr)
}
ret->datatype = 'S';
if(bMustFree) free(str);
- if(r[0].datatype == 'S') es_deleteStr(r[0].d.estr);
- if(r[1].datatype == 'S') es_deleteStr(r[1].d.estr);
- if(r[2].datatype == 'S') es_deleteStr(r[2].d.estr);
+ varFreeMembers(&r[0]);
+ varFreeMembers(&r[1]);
+ varFreeMembers(&r[2]);
break;
case CNFFUNC_PRIFILT:
pPrifilt = (struct funcData_prifilt*) func->funcdata;
@@ -1619,20 +1626,28 @@ dbgprintf("DDDD: executing lookup\n");
static inline void
evalVar(struct cnfvar *var, void *usrptr, struct var *ret)
{
+ rs_size_t propLen;
+ uchar *pszProp = NULL;
+ unsigned short bMustBeFreed = 0;
rsRetVal localRet;
- es_str_t *estr;
struct json_object *json;
- if(var->name[0] == '$' && var->name[1] == '!') {
- /* TODO: unify string libs */
- estr = es_newStrFromBuf(var->name+1, strlen(var->name)-1);
- localRet = msgGetCEEPropJSON((msg_t*)usrptr, estr, &json);
- es_deleteStr(estr);
+ if(var->prop.id == PROP_CEE ||
+ var->prop.id == PROP_LOCAL_VAR ||
+ var->prop.id == PROP_GLOBAL_VAR ) {
+ localRet = msgGetJSONPropJSON((msg_t*)usrptr, &var->prop, &json);
ret->datatype = 'J';
ret->d.json = (localRet == RS_RET_OK) ? json : NULL;
+
+ DBGPRINTF("rainerscript: var %d:%s: '%s'\n", var->prop.id, var->prop.name,
+ (ret->d.json == NULL) ? "" : json_object_get_string(ret->d.json));
} else {
ret->datatype = 'S';
- ret->d.estr = cnfGetVar(var->name, usrptr);
+ pszProp = (uchar*) MsgGetProp((msg_t*)usrptr, NULL, &var->prop, &propLen, &bMustBeFreed, NULL);
+ ret->d.estr = es_newStrFromCStr((char*)pszProp, propLen);
+ DBGPRINTF("rainerscript: var %d: '%s'\n", var->prop.id, pszProp);
+ if(bMustBeFreed)
+ free(pszProp);
}
}
@@ -1678,8 +1693,8 @@ evalStrArrayCmp(es_str_t *estr_l, struct cnfarray* ar, int cmpop)
}
#define FREE_BOTH_RET \
- if(r.datatype == 'S') es_deleteStr(r.d.estr); \
- if(l.datatype == 'S') es_deleteStr(l.d.estr)
+ varFreeMembers(&r); \
+ varFreeMembers(&l)
#define COMP_NUM_BINOP(x) \
cnfexprEval(expr->l, &l, usrptr); \
@@ -1706,9 +1721,9 @@ evalStrArrayCmp(es_str_t *estr_l, struct cnfarray* ar, int cmpop)
#define FREE_TWO_STRINGS \
if(bMustFree) es_deleteStr(estr_r); \
- if(expr->r->nodetype != 'S' && expr->r->nodetype != 'A' && r.datatype == 'S') es_deleteStr(r.d.estr); \
+ if(expr->r->nodetype != 'S' && expr->r->nodetype != 'A') varFreeMembers(&r); \
if(bMustFree2) es_deleteStr(estr_l); \
- if(l.datatype == 'S') es_deleteStr(l.d.estr)
+ varFreeMembers(&l)
/* evaluate an expression.
* Note that we try to avoid malloc whenever possible (because of
@@ -1759,7 +1774,7 @@ cnfexprEval(struct cnfexpr *expr, struct var *ret, void* usrptr)
if(bMustFree) es_deleteStr(estr_r);
}
}
- if(r.datatype == 'S') es_deleteStr(r.d.estr);
+ varFreeMembers(&r);
}
} else if(l.datatype == 'J') {
estr_l = var2String(&l, &bMustFree);
@@ -1781,7 +1796,7 @@ cnfexprEval(struct cnfexpr *expr, struct var *ret, void* usrptr)
if(bMustFree) es_deleteStr(estr_r);
}
}
- if(r.datatype == 'S') es_deleteStr(r.d.estr);
+ varFreeMembers(&r);
}
if(bMustFree) es_deleteStr(estr_l);
} else {
@@ -1798,9 +1813,9 @@ cnfexprEval(struct cnfexpr *expr, struct var *ret, void* usrptr)
} else {
ret->d.n = (l.d.n == r.d.n); /*CMP*/
}
- if(r.datatype == 'S') es_deleteStr(r.d.estr);
+ varFreeMembers(&r);
}
- if(l.datatype == 'S') es_deleteStr(l.d.estr);
+ varFreeMembers(&l);
break;
case CMP_NE:
cnfexprEval(expr->l, &l, usrptr);
@@ -2028,9 +2043,9 @@ cnfexprEval(struct cnfexpr *expr, struct var *ret, void* usrptr)
ret->d.n = 1ll;
else
ret->d.n = 0ll;
- if(r.datatype == 'S') es_deleteStr(r.d.estr);
+ varFreeMembers(&r);
}
- if(l.datatype == 'S') es_deleteStr(l.d.estr);
+ varFreeMembers(&l);
break;
case AND:
cnfexprEval(expr->l, &l, usrptr);
@@ -2041,17 +2056,17 @@ cnfexprEval(struct cnfexpr *expr, struct var *ret, void* usrptr)
ret->d.n = 1ll;
else
ret->d.n = 0ll;
- if(r.datatype == 'S') es_deleteStr(r.d.estr);
+ varFreeMembers(&r);
} else {
ret->d.n = 0ll;
}
- if(l.datatype == 'S') es_deleteStr(l.d.estr);
+ varFreeMembers(&l);
break;
case NOT:
cnfexprEval(expr->r, &r, usrptr);
ret->datatype = 'N';
ret->d.n = !var2Number(&r, &convok_r);
- if(r.datatype == 'S') es_deleteStr(r.d.estr);
+ varFreeMembers(&r);
break;
case 'N':
ret->datatype = 'N';
@@ -2102,7 +2117,7 @@ cnfexprEval(struct cnfexpr *expr, struct var *ret, void* usrptr)
cnfexprEval(expr->r, &r, usrptr);
ret->datatype = 'N';
ret->d.n = -var2Number(&r, &convok_r);
- if(r.datatype == 'S') es_deleteStr(r.d.estr);
+ varFreeMembers(&r);
break;
case 'F':
doFuncCall((struct cnffunc*) expr, ret, usrptr);
@@ -2195,6 +2210,7 @@ cnfexprDestruct(struct cnfexpr *expr)
break;
case 'V':
free(((struct cnfvar*)expr)->name);
+ msgPropDescrDestruct(&(((struct cnfvar*)expr)->prop));
break;
case 'F':
cnffuncDestruct((struct cnffunc*)expr);
@@ -2452,12 +2468,10 @@ cnfstmtPrintOnly(struct cnfstmt *stmt, int indent, sbool subtree)
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);
+ propIDToName(stmt->d.s_propfilt.prop.id));
+ if(stmt->d.s_propfilt.prop.name != NULL) {
doIndent(indent);
- dbgprintf("\tCEE-Prop.: '%s'\n", cstr);
- free(cstr);
+ dbgprintf("\tCEE-Prop.: '%s'\n", stmt->d.s_propfilt.prop.name);
}
doIndent(indent); dbgprintf("\tOperation: ");
if(stmt->d.s_propfilt.isNegated)
@@ -2564,6 +2578,7 @@ cnfvarNew(char *name)
if((var = malloc(sizeof(struct cnfvar))) != NULL) {
var->nodetype = 'V';
var->name = name;
+ msgPropDescrFill(&var->prop, (uchar*)var->name, strlen(var->name));
}
return var;
}
@@ -2617,8 +2632,7 @@ cnfstmtDestruct(struct cnfstmt *stmt)
cnfstmtDestructLst(stmt->d.s_prifilt.t_else);
break;
case S_PROPFILT:
- if(stmt->d.s_propfilt.propName != NULL)
- es_deleteStr(stmt->d.s_propfilt.propName);
+ msgPropDescrDestruct(&stmt->d.s_propfilt.prop);
if(stmt->d.s_propfilt.regex_cache != NULL)
rsCStrRegexDestruct(&stmt->d.s_propfilt.regex_cache);
if(stmt->d.s_propfilt.pCSCompValue != NULL)
@@ -2703,7 +2717,6 @@ cnfstmtNewPROPFILT(char *propfilt, struct cnfstmt *t_then)
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;
if(DecodePropFilter((uchar*)propfilt, cnfstmt) != RS_RET_OK) {
diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h
index 4a508f93..001dff4e 100644
--- a/grammar/rainerscript.h
+++ b/grammar/rainerscript.h
@@ -6,7 +6,6 @@
#include <sys/types.h>
#include <regex.h>
-
#define LOG_NFACILITIES 24 /* current number of syslog facilities */
#define CNFFUNC_MAX_ARGS 32
/**< maximum number of arguments that any function can have (among
@@ -182,8 +181,7 @@ struct cnfstmt {
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 */
+ msgPropDescr_t prop; /* requested property */
struct cnfstmt *t_then;
struct cnfstmt *t_else;
} s_propfilt;
@@ -210,6 +208,7 @@ struct cnfstringval {
struct cnfvar {
unsigned nodetype;
char *name;
+ msgPropDescr_t prop;
};
struct cnfarray {
diff --git a/grammar/testdriver.c b/grammar/testdriver.c
index b29626d4..58d204a3 100644
--- a/grammar/testdriver.c
+++ b/grammar/testdriver.c
@@ -87,15 +87,6 @@ void cnfDoBSDHost(char *ln)
dbgprintf("global:BSD host: %s\n", ln);
}
-es_str_t*
-cnfGetVar(char __attribute__((unused)) *name,
- void __attribute__((unused)) *usrptr)
-{
- es_str_t *estr;
- estr = es_newStrFromCStr("", 1);
- return estr;
-}
-
int
main(int argc, char *argv[])
{
diff --git a/plugins/ommongodb/ommongodb.c b/plugins/ommongodb/ommongodb.c
index a7c42010..af1f5a37 100644
--- a/plugins/ommongodb/ommongodb.c
+++ b/plugins/ommongodb/ommongodb.c
@@ -235,12 +235,18 @@ getDefaultBSON(msg_t *pMsg)
int severity, facil;
gint64 ts_gen, ts_rcv; /* timestamps: generated, received */
int secfrac;
-
- procid = MsgGetProp(pMsg, NULL, PROP_PROGRAMNAME, NULL, &procid_len, &procid_free, NULL);
- tag = MsgGetProp(pMsg, NULL, PROP_SYSLOGTAG, NULL, &tag_len, &tag_free, NULL);
- pid = MsgGetProp(pMsg, NULL, PROP_PROCID, NULL, &pid_len, &pid_free, NULL);
- sys = MsgGetProp(pMsg, NULL, PROP_HOSTNAME, NULL, &sys_len, &sys_free, NULL);
- msg = MsgGetProp(pMsg, NULL, PROP_MSG, NULL, &msg_len, &msg_free, NULL);
+ msgPropDescr_t cProp; /* we use internal implementation knowledge... */
+
+ cProp.id = PROP_PROGRAMNAME;
+ procid = MsgGetProp(pMsg, NULL, &cProp, &procid_len, &procid_free, NULL);
+ cProp.id = PROP_SYSLOGTAG;
+ tag = MsgGetProp(pMsg, NULL, &cProp, &tag_len, &tag_free, NULL);
+ cProp.id = PROP_PROCID;
+ pid = MsgGetProp(pMsg, NULL, &cProp, &pid_len, &pid_free, NULL);
+ cProp.id = PROP_HOSTNAME;
+ sys = MsgGetProp(pMsg, NULL, &cProp, &sys_len, &sys_free, NULL);
+ cProp.id = PROP_MSG;
+ msg = MsgGetProp(pMsg, NULL, &cProp, &msg_len, &msg_free, NULL);
// TODO: move to datetime? Refactor in any case! rgerhards, 2012-03-30
ts_gen = (gint64) datetime.syslogTime2time_t(&pMsg->tTIMESTAMP) * 1000; /* ms! */
diff --git a/runtime/msg.c b/runtime/msg.c
index 9f5bcde2..907000c4 100644
--- a/runtime/msg.c
+++ b/runtime/msg.c
@@ -65,6 +65,7 @@
#include "net.h"
#include "var.h"
#include "rsconf.h"
+#include "parserif.h"
/* TODO: move the global variable root to the config object - had no time to to it
* right now before vacation -- rgerhards, 2013-07-22
@@ -326,7 +327,6 @@ static int getAPPNAMELen(msg_t *pM, sbool bLockMutex);
static rsRetVal jsonPathFindParent(struct json_object *jroot, uchar *name, uchar *leaf, struct json_object **parent, int bCreate);
static uchar * jsonPathGetLeaf(uchar *name, int lenName);
static struct json_object *jsonDeepCopy(struct json_object *src);
-static rsRetVal msgAddJSONObj(msg_t *pM, uchar *name, struct json_object *json, struct json_object **pjroot);
/* the locking and unlocking implementations: */
@@ -452,14 +452,12 @@ getRcvFromIP(msg_t *pM)
}
-/* map a property name (C string) to a property ID */
+/* map a property name (string) to a property ID */
rsRetVal
-propNameStrToID(uchar *pName, propid_t *pPropID)
+propNameToID(uchar *pName, propid_t *pPropID)
{
DEFiRet;
- assert(pName != NULL);
-
/* sometimes there are aliases to the original MonitoWare
* property names. These come after || in the ifs below. */
if(!strcmp((char*) pName, "msg")) {
@@ -534,16 +532,16 @@ propNameStrToID(uchar *pName, propid_t *pPropID)
*pPropID = PROP_SYS_MYHOSTNAME;
} else if(!strcmp((char*) pName, "$!all-json")) {
*pPropID = PROP_CEE_ALL_JSON;
- } else if(!strncmp((char*) pName, "$!", 2)) {
- *pPropID = PROP_CEE;
- } else if(!strncmp((char*) pName, "$.", 2)) {
- *pPropID = PROP_LOCAL_VAR;
- } else if(!strncmp((char*) pName, "$/", 2)) {
- *pPropID = PROP_GLOBAL_VAR;
} else if(!strcmp((char*) pName, "$bom")) {
*pPropID = PROP_SYS_BOM;
} else if(!strcmp((char*) pName, "$uptime")) {
*pPropID = PROP_SYS_UPTIME;
+ } else if(!strncmp((char*) pName, "$!", 2) || pName[0] == '!') {
+ *pPropID = PROP_CEE;
+ } else if(!strncmp((char*) pName, "$.", 2) || pName[0] == '.') {
+ *pPropID = PROP_LOCAL_VAR;
+ } else if(!strncmp((char*) pName, "$/", 2) || pName[0] == '/') {
+ *pPropID = PROP_GLOBAL_VAR;
} else {
DBGPRINTF("PROP_INVALID for name '%s'\n", pName);
*pPropID = PROP_INVALID;
@@ -554,21 +552,6 @@ propNameStrToID(uchar *pName, propid_t *pPropID)
}
-/* map a property name (string) to a property ID */
-rsRetVal
-propNameToID(cstr_t *pCSPropName, propid_t *pPropID)
-{
- uchar *pName;
- DEFiRet;
-
- assert(pCSPropName != NULL);
- assert(pPropID != NULL);
- pName = rsCStrGetSzStrNoNULL(pCSPropName);
- iRet = propNameStrToID(pName, pPropID);
- RETiRet;
-}
-
-
/* map a property ID to a name string (useful for displaying) */
uchar *propIDToName(propid_t propID)
{
@@ -641,8 +624,6 @@ uchar *propIDToName(propid_t propID)
return UCHAR_CONSTANT("*CEE-based property*");
case PROP_LOCAL_VAR:
return UCHAR_CONSTANT("*LOCAL_VARIABLE*");
- case PROP_GLOBAL_VAR:
- return UCHAR_CONSTANT("*GLOBAL_VARIABLE*");
case PROP_CEE_ALL_JSON:
return UCHAR_CONSTANT("$!all-json");
case PROP_SYS_BOM:
@@ -2489,11 +2470,17 @@ typedef enum ENOWType { NOW_NOW, NOW_YEAR, NOW_MONTH, NOW_DAY, NOW_HOUR, NOW_HHO
static uchar *getNOW(eNOWType eNow, struct syslogTime *t)
{
uchar *pBuf;
+ struct syslogTime tt;
if((pBuf = (uchar*) MALLOC(sizeof(uchar) * tmpBUFSIZE)) == NULL) {
return NULL;
}
+ if(t == NULL) { /* can happen if called via script engine */
+ datetime.getCurrTime(&tt, NULL);
+ t = &tt;
+ }
+
if(t->year == 0) { /* not yet set! */
datetime.getCurrTime(t, NULL);
}
@@ -2537,11 +2524,11 @@ static uchar *getNOW(eNOWType eNow, struct syslogTime *t)
/* Get a JSON-Property as string value (used for various types of JSON-based vars) */
-static rsRetVal
-getJSONPropVal(struct json_object *jroot, es_str_t *propName, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed)
+rsRetVal
+getJSONPropVal(msg_t *pMsg, msgPropDescr_t *pProp, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed)
{
- uchar *name = NULL;
uchar *leaf;
+ struct json_object *jroot;
struct json_object *parent;
struct json_object *field;
DEFiRet;
@@ -2549,15 +2536,26 @@ getJSONPropVal(struct json_object *jroot, es_str_t *propName, uchar **pRes, rs_s
if(*pbMustBeFreed)
free(*pRes);
*pRes = NULL;
- // TODO: mutex?
+
+ if(pProp->id == PROP_CEE) {
+ jroot = pMsg->json;
+ } else if(pProp->id == PROP_LOCAL_VAR) {
+ jroot = pMsg->localvars;
+ } else if(pProp->id == PROP_GLOBAL_VAR) {
+ pthread_rwlock_rdlock(&glblVars_rwlock);
+ jroot = global_var_root;
+ } else {
+ DBGPRINTF("msgGetJSONPropVal; invalid property id %d\n",
+ pProp->id);
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
if(jroot == NULL) goto finalize_it;
- if(!es_strbufcmp(propName, (uchar*)"!", 1)) {
+ if(!strcmp((char*)pProp->name, "!")) {
field = jroot;
} else {
- name = (uchar*)es_str2cstr(propName, NULL);
- leaf = jsonPathGetLeaf(name+1, ustrlen(name-1));
- CHKiRet(jsonPathFindParent(jroot, name+1, leaf, &parent, 1));
+ leaf = jsonPathGetLeaf(pProp->name, pProp->nameLen);
+ CHKiRet(jsonPathFindParent(jroot, pProp->name, leaf, &parent, 1));
field = json_object_object_get(parent, (char*)leaf);
}
if(field != NULL) {
@@ -2567,7 +2565,8 @@ getJSONPropVal(struct json_object *jroot, es_str_t *propName, uchar **pRes, rs_s
}
finalize_it:
- free(name);
+ if(pProp->id == PROP_GLOBAL_VAR)
+ pthread_rwlock_unlock(&glblVars_rwlock);
if(*pRes == NULL) {
/* could not find any value, so set it to empty */
*pRes = (unsigned char*)"";
@@ -2576,81 +2575,51 @@ finalize_it:
RETiRet;
}
-rsRetVal
-getCEEPropVal(msg_t *pM, es_str_t *propName, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed)
-{
- return getJSONPropVal(pM->json, propName, pRes, buflen, pbMustBeFreed);
-}
-
-rsRetVal
-getLocalVarPropVal(msg_t *pM, es_str_t *propName, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed)
-{
- return getJSONPropVal(pM->localvars, propName, pRes, buflen, pbMustBeFreed);
-}
-
-rsRetVal
-getGlobalVarPropVal( es_str_t *propName, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed)
-{
- DEFiRet;
- pthread_rwlock_rdlock(&glblVars_rwlock);
- iRet = getJSONPropVal(global_var_root, propName, pRes, buflen, pbMustBeFreed);
- pthread_rwlock_unlock(&glblVars_rwlock);
- RETiRet;
-}
-
/* Get a JSON-based-variable as native json object */
rsRetVal
-msgGetJSONPropJSON(struct json_object *jroot, es_str_t *propName, struct json_object **pjson)
+msgGetJSONPropJSON(msg_t *pMsg, msgPropDescr_t *pProp, struct json_object **pjson)
{
- uchar *name = NULL;
+ struct json_object *jroot;
uchar *leaf;
struct json_object *parent;
DEFiRet;
- // TODO: mutex?
+ if(pProp->id == PROP_CEE) {
+ jroot = pMsg->json;
+ } else if(pProp->id == PROP_LOCAL_VAR) {
+ jroot = pMsg->localvars;
+ } else if(pProp->id == PROP_GLOBAL_VAR) {
+ pthread_rwlock_rdlock(&glblVars_rwlock);
+ jroot = global_var_root;
+ } else {
+ DBGPRINTF("msgGetJSONPropJSON; invalid property id %d\n",
+ pProp->id);
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
if(jroot == NULL) {
+ DBGPRINTF("msgGetJSONPropJSON; jroot empty for property %s\n",
+ pProp->name);
ABORT_FINALIZE(RS_RET_NOT_FOUND);
}
- if(!es_strbufcmp(propName, (uchar*)"!", 1)) {
+ if(!strcmp((char*)pProp->name, "!")) {
*pjson = jroot;
FINALIZE;
}
- name = (uchar*)es_str2cstr(propName, NULL);
- leaf = jsonPathGetLeaf(name, ustrlen(name));
- CHKiRet(jsonPathFindParent(jroot, name, leaf, &parent, 1));
+ leaf = jsonPathGetLeaf(pProp->name, pProp->nameLen);
+ CHKiRet(jsonPathFindParent(jroot, pProp->name, leaf, &parent, 1));
*pjson = json_object_object_get(parent, (char*)leaf);
if(*pjson == NULL) {
ABORT_FINALIZE(RS_RET_NOT_FOUND);
}
finalize_it:
- free(name);
+ if(pProp->id == PROP_GLOBAL_VAR)
+ pthread_rwlock_unlock(&glblVars_rwlock);
RETiRet;
}
-rsRetVal
-msgGetCEEPropJSON(msg_t *pM, es_str_t *propName, struct json_object **pjson)
-{
- return msgGetJSONPropJSON(pM->json, propName, pjson);
-}
-
-rsRetVal
-msgGetLocalVarJSON(msg_t *pM, es_str_t *propName, struct json_object **pjson)
-{
- return msgGetJSONPropJSON(pM->localvars, propName, pjson);
-}
-
-rsRetVal
-msgGetGlobalVarJSON(es_str_t *propName, struct json_object **pjson)
-{
- DEFiRet;
- pthread_rwlock_rdlock(&glblVars_rwlock);
- iRet = msgGetJSONPropJSON(global_var_root, propName, pjson);
- pthread_rwlock_unlock(&glblVars_rwlock);
- RETiRet;
-}
/* Encode a JSON value and add it to provided string. Note that
* the string object may be NULL. In this case, it is created
@@ -2852,7 +2821,7 @@ finalize_it:
*pPropLen = sizeof("**OUT OF MEMORY**") - 1; \
return(UCHAR_CONSTANT("**OUT OF MEMORY**"));}
uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
- propid_t propid, es_str_t *propName, rs_size_t *pPropLen,
+ msgPropDescr_t *pProp, rs_size_t *pPropLen,
unsigned short *pbMustBeFreed, struct syslogTime *ttNow)
{
uchar *pRes; /* result pointer */
@@ -2875,7 +2844,7 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
*pbMustBeFreed = 0;
- switch(propid) {
+ switch(pProp->id) {
case PROP_MSG:
pRes = getMSG(pMsg);
bufLen = getMSGLen(pMsg);
@@ -3047,13 +3016,9 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
}
break;
case PROP_CEE:
- getCEEPropVal(pMsg, propName, &pRes, &bufLen, pbMustBeFreed);
- break;
case PROP_LOCAL_VAR:
- getLocalVarPropVal(pMsg, propName, &pRes, &bufLen, pbMustBeFreed);
- break;
case PROP_GLOBAL_VAR:
- getGlobalVarPropVal(propName, &pRes, &bufLen, pbMustBeFreed);
+ getJSONPropVal(pMsg, pProp, &pRes, &bufLen, pbMustBeFreed);
break;
case PROP_SYS_BOM:
if(*pbMustBeFreed == 1)
@@ -3114,7 +3079,7 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
/* there is no point in continuing, we may even otherwise render the
* error message unreadable. rgerhards, 2007-07-10
*/
- dbgprintf("invalid property id: '%d'\n", propid);
+ dbgprintf("invalid property id: '%d'\n", pProp->id);
*pbMustBeFreed = 0;
*pPropLen = sizeof("**INVALID PROPERTY NAME**") - 1;
return UCHAR_CONSTANT("**INVALID PROPERTY NAME**");
@@ -3722,80 +3687,6 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
}
-/* The function returns a json variable suitable for use with RainerScript.
- * Note: caller must free the returned string.
- * Note that we need to do a lot of conversions between es_str_t and cstr -- this will go away once
- * we have moved larger parts of rsyslog to es_str_t. Acceptable for the moment, especially as we intend
- * to rewrite the script engine as well!
- * rgerhards, 2010-12-03
- */
-static es_str_t*
-msgGetJSONVarNew(msg_t *pMsg, struct json_object *jroot, char *name)
-{
- uchar *leaf;
- char *val;
- es_str_t *estr = NULL;
- struct json_object *json, *parent;
-
- ISOBJ_TYPE_assert(pMsg, msg);
-
- if(jroot == NULL) {
- estr = es_newStr(1);
- goto done;
- }
- leaf = jsonPathGetLeaf((uchar*)name, strlen(name));
- if(jsonPathFindParent(jroot, (uchar*)name, leaf, &parent, 1) != RS_RET_OK) {
- estr = es_newStr(1);
- goto done;
- }
- json = json_object_object_get(parent, (char*)leaf);
- val = (char*)json_object_get_string(json);
- estr = es_newStrFromCStr(val, strlen(val));
-done:
- return estr;
-}
-
-es_str_t*
-msgGetCEEVarNew(msg_t *pMsg, char *name)
-{
- return msgGetJSONVarNew(pMsg, pMsg->json, name);
-}
-
-es_str_t*
-msgGetLocalVarNew(msg_t *pMsg, char *name)
-{
- return msgGetJSONVarNew(pMsg, pMsg->localvars, name);
-}
-
-/* Return an es_str_t for given message property.
- */
-es_str_t*
-msgGetMsgVarNew(msg_t *pThis, uchar *name)
-{
- rs_size_t propLen;
- uchar *pszProp = NULL;
- propid_t propid;
- unsigned short bMustBeFreed = 0;
- es_str_t *estr;
- es_str_t *propName;
-
- ISOBJ_TYPE_assert(pThis, msg);
-
- /* always call MsgGetProp() without a template specifier */
- /* TODO: optimize propNameToID() call -- rgerhards, 2009-06-26 */
- propNameStrToID(name, &propid);
- propName = es_newStrFromCStr((char*)name, ustrlen(name)); // TODO: optimize!
- pszProp = (uchar*) MsgGetProp(pThis, NULL, propid, propName, &propLen, &bMustBeFreed, NULL);
- es_deleteStr(propName);
-
- estr = es_newStrFromCStr((char*)pszProp, propLen);
- if(bMustBeFreed)
- free(pszProp);
-
- return estr;
-}
-
-
/* This function can be used as a generic way to set properties.
* We have to handle a lot of legacy, so our return value is not always
* 100% correct (called functions do not always provide one, should
@@ -3981,9 +3872,8 @@ DBGPRINTF("AAAA jsonMerge adds '%s'\n", it.key);
/* find a JSON structure element (field or container doesn't matter). */
rsRetVal
-jsonFind(struct json_object *jroot, es_str_t *propName, struct json_object **jsonres)
+jsonFind(struct json_object *jroot, msgPropDescr_t *pProp, struct json_object **jsonres)
{
- uchar *name = NULL;
uchar *leaf;
struct json_object *parent;
struct json_object *field;
@@ -3994,31 +3884,39 @@ jsonFind(struct json_object *jroot, es_str_t *propName, struct json_object **jso
goto finalize_it;
}
- if(!es_strbufcmp(propName, (uchar*)"!", 1)) {
+ if(!strcmp((char*)pProp->name, "!")) {
field = jroot;
} else {
- name = (uchar*)es_str2cstr(propName, NULL);
- leaf = jsonPathGetLeaf(name, ustrlen(name));
- CHKiRet(jsonPathFindParent(jroot, name, leaf, &parent, 0));
+ leaf = jsonPathGetLeaf(pProp->name, pProp->nameLen);
+ CHKiRet(jsonPathFindParent(jroot, pProp->name, leaf, &parent, 0));
field = json_object_object_get(parent, (char*)leaf);
}
*jsonres = field;
finalize_it:
- free(name);
RETiRet;
}
-static rsRetVal
-msgAddJSONObj(msg_t *pM, uchar *name, struct json_object *json, struct json_object **pjroot)
+rsRetVal
+msgAddJSON(msg_t *pM, uchar *name, struct json_object *json)
{
/* TODO: error checks! This is a quick&dirty PoC! */
+ struct json_object **pjroot;
struct json_object *parent, *leafnode;
uchar *leaf;
DEFiRet;
MsgLock(pM);
- if((name[0] == '!' || name[0] == '.' || name[0] == '/') && name[1] == '\0') {
+ if(name[0] == '!') {
+ pjroot = &pM->json;
+ } else if(name[0] == '.') {
+ pjroot = &pM->localvars;
+ } else { /* globl var */
+ pthread_rwlock_wrlock(&glblVars_rwlock);
+ pjroot = &global_var_root;
+ }
+
+ if(name[1] == '\0') { /* full tree? */
if(*pjroot == NULL)
*pjroot = json;
else
@@ -4067,26 +3965,40 @@ msgAddJSONObj(msg_t *pM, uchar *name, struct json_object *json, struct json_obje
}
finalize_it:
+ if(name[0] == '/')
+ pthread_rwlock_unlock(&glblVars_rwlock);
MsgUnlock(pM);
RETiRet;
}
-rsRetVal
-msgAddJSON(msg_t *pM, uchar *name, struct json_object *json) {
- return msgAddJSONObj(pM, name, json, &pM->json);
-}
rsRetVal
-msgDelJSONVar(msg_t *pM, struct json_object **jroot, uchar *name)
+msgDelJSON(msg_t *pM, uchar *name)
{
+ struct json_object **jroot;
struct json_object *parent, *leafnode;
uchar *leaf;
DEFiRet;
dbgprintf("AAAA: unset variable '%s'\n", name);
MsgLock(pM);
- if((name[0] == '!' || name[0] == '.' || name[0] == '/') && name[1] == '\0') {
- /* strange, but I think we should permit this. After all,
+
+ if(name[0] == '!') {
+ jroot = &pM->json;
+ } else if(name[0] == '.') {
+ jroot = &pM->localvars;
+ } else { /* globl var */
+ pthread_rwlock_wrlock(&glblVars_rwlock);
+ jroot = &global_var_root;
+ }
+ if(jroot == NULL) {
+ DBGPRINTF("msgDelJSONVar; jroot empty in unset for property %s\n",
+ name);
+ FINALIZE;
+ }
+
+ if(name[1] == '\0') {
+ /* full tree! Strange, but I think we should permit this. After all,
* we trust rsyslog.conf to be written by the admin.
*/
DBGPRINTF("unsetting JSON root object\n");
@@ -4113,16 +4025,12 @@ DBGPRINTF("AAAA: unset found JSON value path '%s', " "leaf '%s', leafnode %p\n",
}
finalize_it:
+ if(name[0] == '/')
+ pthread_rwlock_unlock(&glblVars_rwlock);
MsgUnlock(pM);
RETiRet;
}
-rsRetVal
-msgDelJSON(msg_t *pM, uchar *name)
-{
- return msgDelJSONVar(pM, &pM->json, name);
-}
-
static struct json_object *
jsonDeepCopy(struct json_object *src)
{
@@ -4200,16 +4108,8 @@ msgSetJSONFromVar(msg_t *pMsg, uchar *varname, struct var *v)
v->datatype);
ABORT_FINALIZE(RS_RET_ERR);
}
- /* we always know strlen(varname) > 2 */
- if(varname[1] == '!')
- msgAddJSONObj(pMsg, varname+1, json, &pMsg->json);
- else if(varname[1] == '.')
- msgAddJSONObj(pMsg, varname+1, json, &pMsg->localvars);
- else { /* global - '/' */
- pthread_rwlock_wrlock(&glblVars_rwlock);
- msgAddJSONObj(pMsg, varname+1, json, &global_var_root);
- pthread_rwlock_unlock(&glblVars_rwlock);
- }
+
+ msgAddJSON(pMsg, varname, json);
finalize_it:
RETiRet;
}
@@ -4235,6 +4135,49 @@ finalize_it:
}
+/* Fill a message propert description. Space must already be alloced
+ * by the caller. This is for efficiency, as we expect this to happen
+ * as part of a larger structure alloc.
+ * Note that CEE/LOCAL_VAR properties can come in either as
+ * "$!xx"/"$.xx" or "!xx"/".xx" - we will unify them here.
+ */
+rsRetVal
+msgPropDescrFill(msgPropDescr_t *pProp, uchar *name, int nameLen)
+{
+ propid_t id;
+ int offs;
+ DEFiRet;
+ if(propNameToID(name, &id) != RS_RET_OK) {
+ parser_errmsg("invalid property '%s'", name);
+ ABORT_FINALIZE(RS_RET_INVLD_PROP);
+ }
+ if(id == PROP_CEE || id == PROP_LOCAL_VAR || id == PROP_GLOBAL_VAR) {
+ /* in these cases, we need the field name for later processing */
+ /* normalize name: remove $ if present */
+ offs = (name[0] == '$') ? 1 : 0;
+ pProp->name = ustrdup(name + offs);
+ pProp->nameLen = nameLen - offs;
+ /* we patch the root name, so that support functions do not need to
+ * check for different root chars. */
+ pProp->name[0] = '!';
+ }
+ pProp->id = id;
+finalize_it:
+ RETiRet;
+}
+
+void
+msgPropDescrDestruct(msgPropDescr_t *pProp)
+{
+ if(pProp != NULL) {
+ if(pProp->id == PROP_CEE ||
+ pProp->id == PROP_LOCAL_VAR ||
+ pProp->id == PROP_GLOBAL_VAR)
+ free(pProp->name);
+ }
+}
+
+
/* dummy */
rsRetVal msgQueryInterface(void) { return RS_RET_NOT_IMPLEMENTED; }
diff --git a/runtime/msg.h b/runtime/msg.h
index ed15622a..a2392a20 100644
--- a/runtime/msg.h
+++ b/runtime/msg.h
@@ -3,7 +3,7 @@
*
* File begun on 2007-07-13 by RGerhards (extracted from syslogd.c)
*
- * Copyright 2007-2012 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2007-2013 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
@@ -183,21 +183,14 @@ void MsgSetMSGoffs(msg_t *pMsg, short offs);
void MsgSetRawMsgWOSize(msg_t *pMsg, char* pszRawMsg);
void MsgSetRawMsg(msg_t *pMsg, char* pszRawMsg, size_t lenMsg);
rsRetVal MsgReplaceMSG(msg_t *pThis, uchar* pszMSG, int lenMSG);
-uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
- propid_t propid, es_str_t *propName,
+uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe, msgPropDescr_t *pProp,
rs_size_t *pPropLen, unsigned short *pbMustBeFreed, struct syslogTime *ttNow);
-rsRetVal msgGetMsgVar(msg_t *pThis, cstr_t *pstrPropName, var_t **ppVar);
-es_str_t* msgGetMsgVarNew(msg_t *pThis, uchar *name);
uchar *getRcvFrom(msg_t *pM);
void getTAG(msg_t *pM, uchar **ppBuf, int *piLen);
char *getTimeReported(msg_t *pM, enum tplFormatTypes eFmt);
char *getPRI(msg_t *pMsg);
void getRawMsg(msg_t *pM, uchar **pBuf, int *piLen);
-rsRetVal msgGetCEEVar(msg_t *pThis, cstr_t *propName, var_t **ppVar);
-es_str_t* msgGetCEEVarNew(msg_t *pMsg, char *name);
-es_str_t* msgGetLocalVarNew(msg_t *pMsg, char *name);
rsRetVal msgAddJSON(msg_t *pM, uchar *name, struct json_object *json);
-rsRetVal getCEEPropVal(msg_t *pM, es_str_t *propName, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed);
rsRetVal MsgGetSeverity(msg_t *pThis, int *piSeverity);
rsRetVal MsgDeserialize(msg_t *pMsg, strm_t *pStrm);
@@ -213,20 +206,16 @@ char *getHOSTNAME(msg_t *pM);
int getHOSTNAMELen(msg_t *pM);
uchar *getProgramName(msg_t *pM, sbool bLockMutex);
uchar *getRcvFrom(msg_t *pM);
-rsRetVal propNameToID(cstr_t *pCSPropName, propid_t *pPropID);
+rsRetVal propNameToID(uchar *pName, propid_t *pPropID);
uchar *propIDToName(propid_t propID);
-rsRetVal msgGetCEEPropJSON(msg_t *pM, es_str_t *propName, struct json_object **pjson);
-rsRetVal getGlobalVarPropVal( es_str_t *propName, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed);
-rsRetVal msgGetLocalVarJSON(msg_t *pM, es_str_t *propName, struct json_object **pjson);
-rsRetVal msgGetGlobalVarJSON(es_str_t *propName, struct json_object **pjson);
+rsRetVal msgGetJSONPropJSON(msg_t *pMsg, msgPropDescr_t *pProp, struct json_object **pjson);
+rsRetVal getJSONPropVal(msg_t *pMsg, msgPropDescr_t *pProp, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed);
rsRetVal msgSetJSONFromVar(msg_t *pMsg, uchar *varname, struct var *var);
rsRetVal msgDelJSON(msg_t *pMsg, uchar *varname);
-rsRetVal jsonFind(struct json_object *jroot, es_str_t *propName, struct json_object **jsonres);
+rsRetVal jsonFind(struct json_object *jroot, msgPropDescr_t *pProp, struct json_object **jsonres);
-static inline rsRetVal
-msgUnsetJSON(msg_t *pMsg, uchar *varname) {
- return msgDelJSON(pMsg, varname+1);
-}
+rsRetVal msgPropDescrFill(msgPropDescr_t *pProp, uchar *name, int nameLen);
+void msgPropDescrDestruct(msgPropDescr_t *pProp);
static inline int
msgGetProtocolVersion(msg_t *pM)
diff --git a/runtime/rsconf.c b/runtime/rsconf.c
index 6c7c5fd5..8c808786 100644
--- a/runtime/rsconf.c
+++ b/runtime/rsconf.c
@@ -254,92 +254,6 @@ CODESTARTobjDebugPrint(rsconf)
ENDobjDebugPrint(rsconf)
-/* 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
- * by the caller when no longer needed. If the function
- * can not allocate memory, it returns a NULL pointer.
- * TODO: this was taken from msg.c and we should consolidate it with the code
- * there. This is especially important when we increase the number of system
- * variables (what we definitely want to do).
- */
-typedef enum ENOWType { NOW_NOW, NOW_YEAR, NOW_MONTH, NOW_DAY, NOW_HOUR, NOW_MINUTE } eNOWType;
-static rsRetVal
-getNOW(eNOWType eNow, es_str_t **estr)
-{
- DEFiRet;
- uchar szBuf[16];
- struct syslogTime t;
- es_size_t len;
-
- datetime.getCurrTime(&t, NULL);
- switch(eNow) {
- case NOW_NOW:
- len = snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar),
- "%4.4d-%2.2d-%2.2d", t.year, t.month, t.day);
- break;
- case NOW_YEAR:
- len = snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "%4.4d", t.year);
- break;
- case NOW_MONTH:
- len = snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "%2.2d", t.month);
- break;
- case NOW_DAY:
- len = snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "%2.2d", t.day);
- break;
- case NOW_HOUR:
- len = snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "%2.2d", t.hour);
- break;
- case NOW_MINUTE:
- len = snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "%2.2d", t.minute);
- break;
- default:
- len = snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "*invld eNow*");
- break;
- }
-
- /* now create a string object out of it and hand that over to the var */
- *estr = es_newStrFromCStr((char*)szBuf, len);
-
- RETiRet;
-}
-
-
-
-static inline es_str_t *
-getSysVar(char *name)
-{
- es_str_t *estr = NULL;
- rsRetVal iRet = RS_RET_OK;
-
- if(!strcmp(name, "now")) {
- CHKiRet(getNOW(NOW_NOW, &estr));
- } else if(!strcmp(name, "year")) {
- CHKiRet(getNOW(NOW_YEAR, &estr));
- } else if(!strcmp(name, "month")) {
- CHKiRet(getNOW(NOW_MONTH, &estr));
- } else if(!strcmp(name, "day")) {
- CHKiRet(getNOW(NOW_DAY, &estr));
- } else if(!strcmp(name, "hour")) {
- CHKiRet(getNOW(NOW_HOUR, &estr));
- } else if(!strcmp(name, "minute")) {
- CHKiRet(getNOW(NOW_MINUTE, &estr));
- } else if(!strcmp(name, "myhostname")) {
- char *hn = (char*)glbl.GetLocalHostName();
- estr = es_newStrFromCStr(hn, strlen(hn));
- } else {
- ABORT_FINALIZE(RS_RET_SYSVAR_NOT_FOUND);
- }
-finalize_it:
- if(iRet != RS_RET_OK) {
- dbgprintf("getSysVar error iRet %d\n", iRet);
- if(estr == NULL)
- estr = es_newStrFromCStr("*ERROR*", sizeof("*ERROR*") - 1);
- }
- return estr;
-}
-
-
/* Process input() objects */
rsRetVal
inputProcessCnf(struct cnfobj *o)
@@ -479,30 +393,6 @@ void cnfDoBSDHost(char *ln)
"solution (Block '%s')", ln);
free(ln);
}
-
-es_str_t*
-cnfGetVar(char *name, void *usrptr)
-{
- es_str_t *estr;
- if(name[0] == '$') {
- if(name[1] == '$')
- estr = getSysVar(name+2);
- else if(name[1] == '!')
- estr = msgGetCEEVarNew((msg_t*) usrptr, name+2);
- else
- estr = msgGetMsgVarNew((msg_t*) usrptr, (uchar*)name);
- } else { /* if this happens, we have a program logic error */
- estr = es_newStrFromCStr("err: var must start with $",
- sizeof("err: var must start with $")-1);
- }
- if(Debug) {
- char *s;
- s = es_str2cstr(estr, NULL);
- dbgprintf("rainerscript: var '%s': '%s'\n", name, s);
- free(s);
- }
- return estr;
-}
/*------------------------------ end interface to flex/bison parser ------------------------------*/
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index 85381b8d..edf0c593 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -102,52 +102,6 @@
#define _PATH_CONSOLE "/dev/console"
#endif
-/* properties are now encoded as (tiny) integers. I do not use an enum as I would like
- * to keep the memory footprint small (and thus cache hits high).
- * rgerhards, 2009-06-26
- */
-typedef uintTiny propid_t;
-#define PROP_INVALID 0
-#define PROP_MSG 1
-#define PROP_TIMESTAMP 2
-#define PROP_HOSTNAME 3
-#define PROP_SYSLOGTAG 4
-#define PROP_RAWMSG 5
-#define PROP_INPUTNAME 6
-#define PROP_FROMHOST 7
-#define PROP_FROMHOST_IP 8
-#define PROP_PRI 9
-#define PROP_PRI_TEXT 10
-#define PROP_IUT 11
-#define PROP_SYSLOGFACILITY 12
-#define PROP_SYSLOGFACILITY_TEXT 13
-#define PROP_SYSLOGSEVERITY 14
-#define PROP_SYSLOGSEVERITY_TEXT 15
-#define PROP_TIMEGENERATED 16
-#define PROP_PROGRAMNAME 17
-#define PROP_PROTOCOL_VERSION 18
-#define PROP_STRUCTURED_DATA 19
-#define PROP_APP_NAME 20
-#define PROP_PROCID 21
-#define PROP_MSGID 22
-#define PROP_PARSESUCCESS 23
-#define PROP_SYS_NOW 150
-#define PROP_SYS_YEAR 151
-#define PROP_SYS_MONTH 152
-#define PROP_SYS_DAY 153
-#define PROP_SYS_HOUR 154
-#define PROP_SYS_HHOUR 155
-#define PROP_SYS_QHOUR 156
-#define PROP_SYS_MINUTE 157
-#define PROP_SYS_MYHOSTNAME 158
-#define PROP_SYS_BOM 159
-#define PROP_SYS_UPTIME 160
-#define PROP_UUID 161
-#define PROP_CEE 200
-#define PROP_CEE_ALL_JSON 201
-#define PROP_LOCAL_VAR 202
-#define PROP_GLOBAL_VAR 203
-
/* The error codes below are orginally "borrowed" from
* liblogging. As such, we reserve values up to -2999
@@ -401,7 +355,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
RS_RET_RULESET_EXISTS = -2306,/**< ruleset already exists */
RS_RET_DEPRECATED = -2307,/**< deprecated functionality is used */
RS_RET_DS_PROP_SEQ_ERR = -2308,/**< property sequence error deserializing object */
- RS_RET_TPL_INVLD_PROP = -2309,/**< property name error in template (unknown name) */
+ RS_RET_INVLD_PROP = -2309,/**< property name error (unknown name) */
RS_RET_NO_RULEBASE = -2310,/**< mmnormalize: rulebase can not be found or otherwise invalid */
RS_RET_INVLD_MODE = -2311,/**< invalid mode specified in configuration */
RS_RET_INVLD_ANON_BITS = -2312,/**< mmanon: invalid number of bits to anonymize specified */
diff --git a/runtime/ruleset.c b/runtime/ruleset.c
index dae5bbaa..15e9e5ea 100644
--- a/runtime/ruleset.c
+++ b/runtime/ruleset.c
@@ -261,7 +261,7 @@ execUnset(struct cnfstmt *stmt, batch_t *pBatch, sbool *active)
for(i = 0 ; i < batchNumMsgs(pBatch) && !*(pBatch->pbShutdownImmediate) ; ++i) {
if( pBatch->eltState[i] != BATCH_STATE_DISC
&& (active == NULL || active[i])) {
- msgUnsetJSON(pBatch->pElem[i].pMsg, stmt->d.s_unset.varname);
+ msgDelJSON(pBatch->pElem[i].pMsg, stmt->d.s_unset.varname);
}
}
RETiRet;
@@ -392,12 +392,11 @@ evalPROPFILT(struct cnfstmt *stmt, msg_t *pMsg)
int bRet = 0;
rs_size_t propLen;
- if(stmt->d.s_propfilt.propID == PROP_INVALID)
+ if(stmt->d.s_propfilt.prop.id == PROP_INVALID)
goto done;
- pszPropVal = MsgGetProp(pMsg, NULL, stmt->d.s_propfilt.propID,
- stmt->d.s_propfilt.propName, &propLen,
- &pbMustBeFreed, NULL);
+ pszPropVal = MsgGetProp(pMsg, NULL, &stmt->d.s_propfilt.prop,
+ &propLen, &pbMustBeFreed, NULL);
/* Now do the compares (short list currently ;)) */
switch(stmt->d.s_propfilt.operation ) {
@@ -441,25 +440,18 @@ evalPROPFILT(struct cnfstmt *stmt, msg_t *pMsg)
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);
+ if(stmt->d.s_propfilt.prop.id == PROP_CEE) {
DBGPRINTF("Filter: check for CEE property '%s' (value '%s') ",
- cstr, pszPropVal);
- free(cstr);
- } else if(stmt->d.s_propfilt.propID == PROP_LOCAL_VAR) {
- cstr = es_str2cstr(stmt->d.s_propfilt.propName, NULL);
+ stmt->d.s_propfilt.prop.name, pszPropVal);
+ } else if(stmt->d.s_propfilt.prop.id == PROP_LOCAL_VAR) {
DBGPRINTF("Filter: check for local var '%s' (value '%s') ",
- cstr, pszPropVal);
- free(cstr);
- } else if(stmt->d.s_propfilt.propID == PROP_GLOBAL_VAR) {
- cstr = es_str2cstr(stmt->d.s_propfilt.propName, NULL);
- DBGPRINTF("Filter: check for global var '%s' (value '%s') ",
- cstr, pszPropVal);
- free(cstr);
+ stmt->d.s_propfilt.prop.name, pszPropVal);
+ //} else if(stmt->d.s_propfilt.propID == PROP_GLOBAL_VAR) {
+ //DBGPRINTF("Filter: check for global var '%s' (value '%s') ",
+ //stmt->d.s_propfilt.propName, pszPropVal);
} else {
DBGPRINTF("Filter: check for property '%s' (value '%s') ",
- propIDToName(stmt->d.s_propfilt.propID), pszPropVal);
+ propIDToName(stmt->d.s_propfilt.prop.id), pszPropVal);
}
if(stmt->d.s_propfilt.isNegated)
DBGPRINTF("NOT ");
diff --git a/runtime/ruleset.h b/runtime/ruleset.h
index cbf8243b..8bfd4920 100644
--- a/runtime/ruleset.h
+++ b/runtime/ruleset.h
@@ -2,7 +2,7 @@
*
* This implements rulesets within rsyslog.
*
- * Copyright 2009-2012 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2009-2013 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
diff --git a/runtime/typedefs.h b/runtime/typedefs.h
index a929b30c..2efd7d65 100644
--- a/runtime/typedefs.h
+++ b/runtime/typedefs.h
@@ -64,6 +64,7 @@ typedef struct nsdsel_ptcp_s nsdsel_ptcp_t;
typedef struct nsdsel_gtls_s nsdsel_gtls_t;
typedef struct nsdpoll_ptcp_s nsdpoll_ptcp_t;
typedef struct wti_s wti_t;
+typedef struct msgPropDescr_s msgPropDescr_t;
typedef struct msg msg_t;
typedef struct queue_s qqueue_t;
typedef struct prop_s prop_t;
@@ -163,6 +164,53 @@ typedef enum {
typedef off_t off64_t;
#endif
+
+/* properties are now encoded as (tiny) integers. I do not use an enum as I would like
+ * to keep the memory footprint small (and thus cache hits high).
+ * rgerhards, 2009-06-26
+ */
+typedef uintTiny propid_t;
+#define PROP_INVALID 0
+#define PROP_MSG 1
+#define PROP_TIMESTAMP 2
+#define PROP_HOSTNAME 3
+#define PROP_SYSLOGTAG 4
+#define PROP_RAWMSG 5
+#define PROP_INPUTNAME 6
+#define PROP_FROMHOST 7
+#define PROP_FROMHOST_IP 8
+#define PROP_PRI 9
+#define PROP_PRI_TEXT 10
+#define PROP_IUT 11
+#define PROP_SYSLOGFACILITY 12
+#define PROP_SYSLOGFACILITY_TEXT 13
+#define PROP_SYSLOGSEVERITY 14
+#define PROP_SYSLOGSEVERITY_TEXT 15
+#define PROP_TIMEGENERATED 16
+#define PROP_PROGRAMNAME 17
+#define PROP_PROTOCOL_VERSION 18
+#define PROP_STRUCTURED_DATA 19
+#define PROP_APP_NAME 20
+#define PROP_PROCID 21
+#define PROP_MSGID 22
+#define PROP_PARSESUCCESS 23
+#define PROP_SYS_NOW 150
+#define PROP_SYS_YEAR 151
+#define PROP_SYS_MONTH 152
+#define PROP_SYS_DAY 153
+#define PROP_SYS_HOUR 154
+#define PROP_SYS_HHOUR 155
+#define PROP_SYS_QHOUR 156
+#define PROP_SYS_MINUTE 157
+#define PROP_SYS_MYHOSTNAME 158
+#define PROP_SYS_BOM 159
+#define PROP_SYS_UPTIME 160
+#define PROP_UUID 161
+#define PROP_CEE 200
+#define PROP_CEE_ALL_JSON 201
+#define PROP_LOCAL_VAR 202
+#define PROP_GLOBAL_VAR 203
+
/* types of configuration handlers
*/
typedef enum cslCmdHdlrType {
@@ -213,6 +261,13 @@ struct multi_submit_s {
msg_t **ppMsgs;
};
+/* the following structure is a helper to describe a message property */
+struct msgPropDescr_s {
+ propid_t id;
+ uchar *name; /* name and lenName are only set for dynamic */
+ int nameLen; /* properties (JSON) */
+};
+
#endif /* multi-include protection */
/* vim:set ai:
*/
diff --git a/template.c b/template.c
index 65de7547..ebb3f422 100644
--- a/template.c
+++ b/template.c
@@ -1,7 +1,7 @@
/* This is the template processing code of rsyslog.
* begun 2004-11-17 rgerhards
*
- * Copyright 2004-2012 Rainer Gerhards and Adiscon
+ * Copyright 2004-2013 Rainer Gerhards and Adiscon
*
* This file is part of rsyslog.
*
@@ -163,13 +163,13 @@ tplToString(struct template *pTpl, msg_t *pMsg, uchar **ppBuf, size_t *pLenBuf,
FINALIZE;
}
- if(pTpl->subtree != NULL) {
+ if(pTpl->bHaveSubtree) {
/* only a single CEE subtree must be provided */
/* note: we could optimize the code below, however, this is
* not worth the effort, as this passing mode is not expected
* in subtree mode and so most probably only used for debug & test.
*/
- getCEEPropVal(pMsg, pTpl->subtree, &pVal, &iLenVal, &bMustBeFreed);
+ getJSONPropVal(pMsg, &pTpl->subtree, &pVal, &iLenVal, &bMustBeFreed);
if(iLenVal >= (rs_size_t)*pLenBuf) /* we reserve one char for the final \0! */
CHKiRet(ExtendBuf(ppBuf, pLenBuf, iLenVal + 1));
memcpy(*ppBuf, pVal, iLenVal+1);
@@ -193,9 +193,8 @@ tplToString(struct template *pTpl, msg_t *pMsg, uchar **ppBuf, size_t *pLenBuf,
iLenVal = pTpe->data.constant.iLenConstant;
bMustBeFreed = 0;
} else if(pTpe->eEntryType == FIELD) {
- pVal = (uchar*) MsgGetProp(pMsg, pTpe, pTpe->data.field.propid,
- pTpe->data.field.propName, &iLenVal,
- &bMustBeFreed, ttNow);
+ pVal = (uchar*) MsgGetProp(pMsg, pTpe, &pTpe->data.field.msgProp,
+ &iLenVal, &bMustBeFreed, ttNow);
/* we now need to check if we should use SQL option. In this case,
* we must go over the generated string and escape '\'' characters.
* rgerhards, 2005-09-22: the option values below look somewhat misplaced,
@@ -264,12 +263,12 @@ tplToArray(struct template *pTpl, msg_t *pMsg, uchar*** ppArr, struct syslogTime
assert(pMsg != NULL);
assert(ppArr != NULL);
- if(pTpl->subtree) {
+ if(pTpl->bHaveSubtree) {
/* Note: this mode is untested, as there is no official plugin
* using array passing, so I simply could not test it.
*/
CHKmalloc(pArr = calloc(2, sizeof(uchar*)));
- getCEEPropVal(pMsg, pTpl->subtree, &pVal, &propLen, &bMustBeFreed);
+ getJSONPropVal(pMsg, &pTpl->subtree, &pVal, &propLen, &bMustBeFreed);
if(bMustBeFreed) { /* if it must be freed, it is our own private copy... */
pArr[0] = pVal; /* ... so we can use it! */
} else {
@@ -290,9 +289,8 @@ tplToArray(struct template *pTpl, msg_t *pMsg, uchar*** ppArr, struct syslogTime
if(pTpe->eEntryType == CONSTANT) {
CHKmalloc(pArr[iArr] = (uchar*)strdup((char*) pTpe->data.constant.pConstant));
} else if(pTpe->eEntryType == FIELD) {
- pVal = (uchar*) MsgGetProp(pMsg, pTpe, pTpe->data.field.propid,
- pTpe->data.field.propName, &propLen,
- &bMustBeFreed, ttNow);
+ pVal = (uchar*) MsgGetProp(pMsg, pTpe, &pTpe->data.field.msgProp,
+ &propLen, &bMustBeFreed, ttNow);
if(bMustBeFreed) { /* if it must be freed, it is our own private copy... */
pArr[iArr] = pVal; /* ... so we can use it! */
} else {
@@ -326,8 +324,8 @@ tplToJSON(struct template *pTpl, msg_t *pMsg, struct json_object **pjson, struct
rsRetVal localRet;
DEFiRet;
- if(pTpl->subtree != NULL){
- localRet = jsonFind(pMsg->json, pTpl->subtree, pjson);
+ if(pTpl->bHaveSubtree){
+ localRet = jsonFind(pMsg->json, &pTpl->subtree, pjson);
if(*pjson == NULL) {
/* we need to have a root object! */
*pjson = json_object_new_object();
@@ -345,8 +343,10 @@ tplToJSON(struct template *pTpl, msg_t *pMsg, struct json_object **pjson, struct
jsonf = json_object_new_string((char*) pTpe->data.constant.pConstant);
json_object_object_add(json, (char*)pTpe->fieldName, jsonf);
} else if(pTpe->eEntryType == FIELD) {
- if(pTpe->data.field.propid == PROP_CEE) {
- localRet = msgGetCEEPropJSON(pMsg, pTpe->data.field.propName, &jsonf);
+ if(pTpe->data.field.msgProp.id == PROP_CEE ||
+ pTpe->data.field.msgProp.id == PROP_LOCAL_VAR ||
+ pTpe->data.field.msgProp.id == PROP_GLOBAL_VAR ) {
+ localRet = msgGetJSONPropJSON(pMsg, &pTpe->data.field.msgProp, &jsonf);
if(localRet == RS_RET_OK) {
json_object_object_add(json, (char*)pTpe->fieldName, json_object_get(jsonf));
} else {
@@ -356,32 +356,9 @@ tplToJSON(struct template *pTpl, msg_t *pMsg, struct json_object **pjson, struct
json_object_object_add(json, (char*)pTpe->fieldName, NULL);
}
}
- } else if(pTpe->data.field.propid == PROP_LOCAL_VAR) {
- localRet = msgGetLocalVarJSON(pMsg, pTpe->data.field.propName, &jsonf);
- if(localRet == RS_RET_OK) {
- json_object_object_add(json, (char*)pTpe->fieldName, json_object_get(jsonf));
- } else {
- DBGPRINTF("tplToJSON: error %d looking up local variable %s\n",
- localRet, pTpe->fieldName);
- if(pTpe->data.field.options.bMandatory) {
- json_object_object_add(json, (char*)pTpe->fieldName, NULL);
- }
- }
- } else if(pTpe->data.field.propid == PROP_GLOBAL_VAR) {
- localRet = msgGetGlobalVarJSON(pTpe->data.field.propName, &jsonf);
- if(localRet == RS_RET_OK) {
- json_object_object_add(json, (char*)pTpe->fieldName, json_object_get(jsonf));
- } else {
- DBGPRINTF("tplToJSON: error %d looking up local variable %s\n",
- localRet, pTpe->fieldName);
- if(pTpe->data.field.options.bMandatory) {
- json_object_object_add(json, (char*)pTpe->fieldName, NULL);
- }
- }
} else {
- pVal = (uchar*) MsgGetProp(pMsg, pTpe, pTpe->data.field.propid,
- pTpe->data.field.propName, &propLen,
- &bMustBeFreed, ttNow);
+ pVal = (uchar*) MsgGetProp(pMsg, pTpe, &pTpe->data.field.msgProp,
+ &propLen, &bMustBeFreed, ttNow);
if(pTpe->data.field.options.bMandatory || propLen > 0) {
jsonf = json_object_new_string_len((char*)pVal, propLen);
json_object_object_add(json, (char*)pTpe->fieldName, jsonf);
@@ -777,7 +754,7 @@ static rsRetVal
do_Parameter(uchar **pp, struct template *pTpl)
{
uchar *p;
- cstr_t *pStrProp;
+ cstr_t *pStrProp = NULL;
cstr_t *pStrField = NULL;
struct templateEntry *pTpe;
int iNum; /* to compute numbers */
@@ -807,26 +784,8 @@ do_Parameter(uchar **pp, struct template *pTpl)
/* got the name */
cstrFinalize(pStrProp);
- if(propNameToID(pStrProp, &pTpe->data.field.propid) != RS_RET_OK) {
- errmsg.LogError(0, RS_RET_TPL_INVLD_PROP, "template '%s': invalid parameter '%s'",
- pTpl->pszName, cstrGetSzStrNoNULL(pStrProp));
- cstrDestruct(&pStrProp);
- ABORT_FINALIZE(RS_RET_TPL_INVLD_PROP);
- }
- if(pTpe->data.field.propid == PROP_CEE) {
- /* in CEE case, we need to preserve the actual property name */
- if((pTpe->data.field.propName = es_newStrFromCStr((char*)cstrGetSzStrNoNULL(pStrProp)+1, cstrLen(pStrProp)-1)) == NULL) {
- cstrDestruct(&pStrProp);
- ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
- }
- } else if(pTpe->data.field.propid == PROP_LOCAL_VAR || pTpe->data.field.propid == PROP_GLOBAL_VAR) {
- /* in these cases, we need to preserve the actual property name, but correct the root ID (bang vs. dot) */
- if((pTpe->data.field.propName = es_newStrFromCStr((char*)cstrGetSzStrNoNULL(pStrProp)+1, cstrLen(pStrProp)-1)) == NULL) {
- cstrDestruct(&pStrProp);
- ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
- }
- es_getBufAddr(pTpe->data.field.propName)[0] = '!'; /* patch root name */
- }
+ CHKiRet(msgPropDescrFill(&pTpe->data.field.msgProp, cstrGetSzStrNoNULL(pStrProp),
+ cstrLen(pStrProp)));
/* Check frompos, if it has an R, then topos should be a regex */
if(*p == ':') {
@@ -1123,8 +1082,7 @@ do_Parameter(uchar **pp, struct template *pTpl)
/* save field name - if none was given, use the property name instead */
if(pStrField == NULL) {
- if(pTpe->data.field.propid == PROP_CEE || pTpe->data.field.propid == PROP_LOCAL_VAR ||
- pTpe->data.field.propid == PROP_GLOBAL_VAR) {
+ if(pTpe->data.field.msgProp.id == PROP_CEE || pTpe->data.field.msgProp.id == PROP_LOCAL_VAR) {
/* in CEE case, we remove "$!"/"$." from the fieldname - it's just our indicator */
pTpe->fieldName = ustrdup(cstrGetSzStrNoNULL(pStrProp)+2);
pTpe->lenFieldName = cstrLen(pStrProp)-2;
@@ -1141,10 +1099,11 @@ do_Parameter(uchar **pp, struct template *pTpl)
DBGPRINTF("template/do_Parameter: fieldName is NULL!\n");
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
- cstrDestruct(&pStrProp);
if(*p) ++p; /* eat '%' */
*pp = p;
finalize_it:
+ if(pStrProp != NULL)
+ cstrDestruct(&pStrProp);
RETiRet;
}
@@ -1605,16 +1564,8 @@ createPropertyTpe(struct template *pTpl, struct cnfobj *o)
/* apply */
CHKmalloc(pTpe = tpeConstruct(pTpl));
pTpe->eEntryType = FIELD;
- CHKiRet(propNameToID(name, &pTpe->data.field.propid));
- if(pTpe->data.field.propid == PROP_CEE) {
- /* in CEE case, we need to preserve the actual property name */
- pTpe->data.field.propName = es_newStrFromCStr((char*)cstrGetSzStrNoNULL(name)+1,
- cstrLen(name)-1);
- } else if(pTpe->data.field.propid == PROP_LOCAL_VAR || pTpe->data.field.propid == PROP_GLOBAL_VAR) {
- /* in these case, we need to preserve the actual property name, but correct the root ID (bang vs. dot) */
- pTpe->data.field.propName = es_newStrFromCStr((char*)cstrGetSzStrNoNULL(name)+1, cstrLen(name)-1);
- es_getBufAddr(pTpe->data.field.propName)[0] = '!'; /* patch root name */
- }
+ CHKiRet(msgPropDescrFill(&pTpe->data.field.msgProp, cstrGetSzStrNoNULL(name),
+ cstrLen(name)));
pTpe->data.field.options.bDropLastLF = droplastlf;
pTpe->data.field.options.bSPIffNo1stSP = spifno1stsp;
pTpe->data.field.options.bMandatory = mandatory;
@@ -1747,8 +1698,9 @@ tplProcessCnf(struct cnfobj *o)
char *name = NULL;
uchar *tplStr = NULL;
uchar *plugin = NULL;
- es_str_t *subtree = NULL;
uchar *p;
+ msgPropDescr_t subtree;
+ sbool bHaveSubtree = 0;
enum { T_STRING, T_PLUGIN, T_LIST, T_SUBTREE }
tplType = T_STRING; /* init just to keep compiler happy: mandatory parameter */
int i;
@@ -1795,10 +1747,11 @@ tplProcessCnf(struct cnfobj *o)
free(name); /* overall assigned */
ABORT_FINALIZE(RS_RET_ERR);
} else {
- /* TODO: unify strings! */
- char *cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
- subtree = es_newStrFromBuf(cstr+1, es_strlen(pvals[i].val.d.estr)-1);
+ uchar *cstr;
+ cstr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ CHKiRet(msgPropDescrFill(&subtree, cstr, ustrlen(cstr)));
free(cstr);
+ bHaveSubtree = 1;
}
} else if(!strcmp(pblk.descr[i].name, "plugin")) {
plugin = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
@@ -1841,7 +1794,7 @@ tplProcessCnf(struct cnfobj *o)
}
}
- if(subtree == NULL) {
+ if(bHaveSubtree) {
if(tplType == T_SUBTREE) {
errmsg.LogError(0, RS_RET_ERR, "template '%s' of type subtree needs "
"subtree parameter", name);
@@ -1911,7 +1864,8 @@ tplProcessCnf(struct cnfobj *o)
break;
case T_LIST: createListTpl(pTpl, o);
break;
- case T_SUBTREE: pTpl->subtree = subtree;
+ case T_SUBTREE: memcpy(&pTpl->subtree, &subtree, sizeof(msgPropDescr_t));
+ pTpl->bHaveSubtree = 1;
break;
}
@@ -2003,9 +1957,8 @@ void tplDeleteAll(rsconf_t *conf)
regexp.regfree(&(pTpeDel->data.field.re));
}
}
- if(pTpeDel->data.field.propName != NULL)
- es_deleteStr(pTpeDel->data.field.propName);
#endif
+ msgPropDescrDestruct(&pTpeDel->data.field.msgProp);
break;
}
free(pTpeDel->fieldName);
@@ -2015,8 +1968,8 @@ void tplDeleteAll(rsconf_t *conf)
pTplDel = pTpl;
pTpl = pTpl->pNext;
free(pTplDel->pszName);
- if(pTplDel->subtree != NULL)
- es_deleteStr(pTplDel->subtree);
+ if(pTplDel->bHaveSubtree)
+ msgPropDescrDestruct(&pTplDel->subtree);
free(pTplDel);
}
ENDfunc
@@ -2063,9 +2016,8 @@ void tplDeleteNew(rsconf_t *conf)
regexp.regfree(&(pTpeDel->data.field.re));
}
}
- if(pTpeDel->data.field.propName != NULL)
- es_deleteStr(pTpeDel->data.field.propName);
#endif
+ msgPropDescrDestruct(&pTpeDel->data.field.msgProp);
break;
}
/*dbgprintf("\n");*/
@@ -2074,8 +2026,8 @@ void tplDeleteNew(rsconf_t *conf)
pTplDel = pTpl;
pTpl = pTpl->pNext;
free(pTplDel->pszName);
- if(pTplDel->subtree != NULL)
- es_deleteStr(pTplDel->subtree);
+ if(pTplDel->bHaveSubtree)
+ msgPropDescrDestruct(&pTplDel->subtree);
free(pTplDel);
}
ENDfunc
@@ -2117,19 +2069,13 @@ void tplPrintList(rsconf_t *conf)
pTpe->data.constant.pConstant);
break;
case FIELD:
- dbgprintf("(FIELD), value: '%d' ", pTpe->data.field.propid);
- if(pTpe->data.field.propid == PROP_CEE) {
- char *cstr = es_str2cstr(pTpe->data.field.propName, NULL);
- dbgprintf("[EE-Property: '%s'] ", cstr);
- free(cstr);
- } else if(pTpe->data.field.propid == PROP_LOCAL_VAR) {
- char *cstr = es_str2cstr(pTpe->data.field.propName, NULL);
- dbgprintf("[Local Var: '%s'] ", cstr);
- free(cstr);
- } else if(pTpe->data.field.propid == PROP_GLOBAL_VAR) {
- char *cstr = es_str2cstr(pTpe->data.field.propName, NULL);
- dbgprintf("[Global Var: '%s'] ", cstr);
- free(cstr);
+ dbgprintf("(FIELD), value: '%d' ", pTpe->data.field.msgProp.id);
+ if(pTpe->data.field.msgProp.id == PROP_CEE) {
+ dbgprintf("[EE-Property: '%s'] ", pTpe->data.field.msgProp.name);
+ } else if(pTpe->data.field.msgProp.id == PROP_LOCAL_VAR) {
+ dbgprintf("[Local Var: '%s'] ", pTpe->data.field.msgProp.name);
+ //} else if(pTpe->data.field.propid == PROP_GLOBAL_VAR) {
+ // dbgprintf("[Global Var: '%s'] ", pTpe->data.field.propName);
}
switch(pTpe->data.field.eDateFormat) {
case tplFmtDefault:
diff --git a/template.h b/template.h
index 87a1c77b..39fbbe03 100644
--- a/template.h
+++ b/template.h
@@ -40,7 +40,8 @@ struct template {
char *pszName;
int iLenName;
rsRetVal (*pStrgen)(msg_t*, uchar**, size_t *);
- es_str_t *subtree; /* subtree name for subtree-type templates */
+ sbool bHaveSubtree;
+ msgPropDescr_t subtree; /* subtree property name for subtree-type templates */
int tpenElements; /* number of elements in templateEntry list */
struct templateEntry *pEntryRoot;
struct templateEntry *pEntryLast;
@@ -79,7 +80,7 @@ struct templateEntry {
int iLenConstant; /* its length */
} constant;
struct {
- propid_t propid; /* property to be used */
+ msgPropDescr_t msgProp; /* property to be used */
unsigned iFromPos; /* for partial strings only chars from this position ... */
unsigned iToPos; /* up to that one... */
unsigned iFieldNr; /* for field extraction: field to extract */
@@ -103,7 +104,6 @@ struct templateEntry {
int field_expand; /* use multiple instances of the field delimiter as a single one? */
#endif
- es_str_t *propName; /**< property name (currently being used for CEE only) */
enum tplFormatTypes eDateFormat;
enum tplFormatCaseConvTypes eCaseConv;