summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/Makefile.am6
-rw-r--r--runtime/conf.c27
-rw-r--r--runtime/ctok.c3
-rw-r--r--runtime/ctok_token.h1
-rw-r--r--runtime/expr.c5
-rw-r--r--runtime/msg.c125
-rw-r--r--runtime/msg.h8
-rw-r--r--runtime/rsyslog.h5
-rw-r--r--runtime/rule.c53
-rw-r--r--runtime/rule.h2
-rw-r--r--runtime/stringbuf.c29
-rw-r--r--runtime/stringbuf.h2
-rw-r--r--runtime/typedefs.h3
-rw-r--r--runtime/var.h1
-rw-r--r--runtime/vm.c27
-rw-r--r--runtime/vmop.h1
16 files changed, 272 insertions, 26 deletions
diff --git a/runtime/Makefile.am b/runtime/Makefile.am
index 09cb6b41..c8e8ce2a 100644
--- a/runtime/Makefile.am
+++ b/runtime/Makefile.am
@@ -110,12 +110,12 @@ librsyslog_la_SOURCES = \
# runtime or will no longer be needed. -- rgerhards, 2008-06-13
if WITH_MODDIRS
-librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/:$(moddirs)\" $(PTHREADS_CFLAGS)
+librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/:$(moddirs)\" $(PTHREADS_CFLAGS) $(LIBEE_CFLAGS)
else
-librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/\" -I$(top_srcdir) $(PTHREADS_CFLAGS)
+librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/\" -I$(top_srcdir) $(PTHREADS_CFLAGS) $(LIBEE_CFLAGS)
endif
#librsyslog_la_LDFLAGS = -module -avoid-version
-librsyslog_la_LIBADD = $(DL_LIBS) $(RT_LIBS)
+librsyslog_la_LIBADD = $(DL_LIBS) $(RT_LIBS) $(LIBEE_LIBS)
#
# regular expression support
diff --git a/runtime/conf.c b/runtime/conf.c
index 1f0badcb..e12cf82b 100644
--- a/runtime/conf.c
+++ b/runtime/conf.c
@@ -874,6 +874,14 @@ static rsRetVal cflineProcessPropFilter(uchar **pline, register rule_t *f)
rsParsDestruct(pPars);
return(iRet);
}
+ if(f->f_filterData.prop.propID == PROP_CEE) {
+ /* in CEE case, we need to preserve the actual property name */
+ if((f->f_filterData.prop.propName =
+ es_newStrFromBuf((char*)cstrGetSzStrNoNULL(pCSPropName)+2, cstrLen(pCSPropName)-2)) == NULL) {
+ cstrDestruct(&pCSPropName);
+ return(RS_RET_ERR);
+ }
+ }
cstrDestruct(&pCSPropName);
/* read operation */
@@ -902,10 +910,13 @@ static rsRetVal cflineProcessPropFilter(uchar **pline, register rule_t *f)
iOffset = 0;
}
+dbgprintf("XXX: offset is %d, string '%s'\n", iOffset, rsCStrGetSzStrNoNULL(pCSCompOp));
if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (uchar*) "contains", 8)) {
f->f_filterData.prop.operation = FIOP_CONTAINS;
} else if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (uchar*) "isequal", 7)) {
f->f_filterData.prop.operation = FIOP_ISEQUAL;
+ } else if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (uchar*) "isempty", 7)) {
+ f->f_filterData.prop.operation = FIOP_ISEMPTY;
} else if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (uchar*) "startswith", 10)) {
f->f_filterData.prop.operation = FIOP_STARTSWITH;
} else if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (unsigned char*) "regex", 5)) {
@@ -918,12 +929,15 @@ static rsRetVal cflineProcessPropFilter(uchar **pline, register rule_t *f)
}
rsCStrDestruct(&pCSCompOp); /* no longer needed */
- /* read compare value */
- iRet = parsQuotedCStr(pPars, &f->f_filterData.prop.pCSCompValue);
- if(iRet != RS_RET_OK) {
- errmsg.LogError(0, iRet, "error %d compare value property - ignoring selector", iRet);
- rsParsDestruct(pPars);
- return(iRet);
+dbgprintf("XXX: fiop is %u\n", (unsigned) f->f_filterData.prop.operation);
+ if(f->f_filterData.prop.operation != FIOP_ISEMPTY) {
+ /* read compare value */
+ iRet = parsQuotedCStr(pPars, &f->f_filterData.prop.pCSCompValue);
+ if(iRet != RS_RET_OK) {
+ errmsg.LogError(0, iRet, "error %d compare value property - ignoring selector", iRet);
+ rsParsDestruct(pPars);
+ return(iRet);
+ }
}
/* skip to action part */
@@ -1065,7 +1079,6 @@ static rsRetVal cflineDoFilter(uchar **pp, rule_t *f)
* and, if so, we copy them over. rgerhards, 2005-10-18
*/
if(pDfltProgNameCmp != NULL) {
-RUNLOG_STR("dflt ProgNameCmp != NULL, setting opCSProgNameComp");
CHKiRet(rsCStrConstructFromCStr(&(f->pCSProgNameComp), pDfltProgNameCmp));
}
diff --git a/runtime/ctok.c b/runtime/ctok.c
index 18ddaed2..6d97568e 100644
--- a/runtime/ctok.c
+++ b/runtime/ctok.c
@@ -277,6 +277,9 @@ ctokGetVar(ctok_t *pThis, ctok_token_t *pToken)
if(c == '$') { /* second dollar, we have a system variable */
pToken->tok = ctok_SYSVAR;
CHKiRet(ctokGetCharFromStream(pThis, &c)); /* "eat" it... */
+ } else if(c == '!') { /* cee variable indicator */
+ pToken->tok = ctok_CEEVAR;
+ CHKiRet(ctokGetCharFromStream(pThis, &c)); /* "eat" it... */
} else {
pToken->tok = ctok_MSGVAR;
}
diff --git a/runtime/ctok_token.h b/runtime/ctok_token.h
index d36689fa..1413c699 100644
--- a/runtime/ctok_token.h
+++ b/runtime/ctok_token.h
@@ -54,6 +54,7 @@ typedef struct {
ctok_FUNCTION = 17,
ctok_THEN = 18,
ctok_STRADD = 19,
+ ctok_CEEVAR = 20,
ctok_CMP_EQ = 100, /* all compare operations must be in a row */
ctok_CMP_NEQ = 101,
ctok_CMP_LT = 102,
diff --git a/runtime/expr.c b/runtime/expr.c
index e449d1c7..01431474 100644
--- a/runtime/expr.c
+++ b/runtime/expr.c
@@ -151,6 +151,11 @@ terminal(expr_t *pThis, ctok_t *tok)
CHKiRet(ctok_token.UnlinkVar(pToken, &pVar));
CHKiRet(vmprg.AddVarOperation(pThis->pVmprg, opcode_PUSHMSGVAR, pVar)); /* add to program */
break;
+ case ctok_CEEVAR:
+ dbgoprint((obj_t*) pThis, "SYSVAR\n");
+ CHKiRet(ctok_token.UnlinkVar(pToken, &pVar));
+ CHKiRet(vmprg.AddVarOperation(pThis->pVmprg, opcode_PUSHCEEVAR, pVar)); /* add to program */
+ break;
case ctok_SYSVAR:
dbgoprint((obj_t*) pThis, "SYSVAR\n");
CHKiRet(ctok_token.UnlinkVar(pToken, &pVar));
diff --git a/runtime/msg.c b/runtime/msg.c
index 82565f18..65ea101f 100644
--- a/runtime/msg.c
+++ b/runtime/msg.c
@@ -37,6 +37,7 @@
#include <ctype.h>
#include <sys/socket.h>
#include <netdb.h>
+#include <libee/libee.h>
#if HAVE_MALLOC_H
# include <malloc.h>
#endif
@@ -444,6 +445,10 @@ rsRetVal propNameToID(cstr_t *pCSPropName, propid_t *pPropID)
*pPropID = PROP_SYS_MINUTE;
} else if(!strcmp((char*) pName, "$myhostname")) {
*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 {
*pPropID = PROP_INVALID;
iRet = RS_RET_VAR_NOT_FOUND;
@@ -525,6 +530,10 @@ uchar *propIDToName(propid_t propID)
return UCHAR_CONSTANT("$MINUTE");
case PROP_SYS_MYHOSTNAME:
return UCHAR_CONSTANT("$MYHOSTNAME");
+ case PROP_CEE:
+ return UCHAR_CONSTANT("*CEE-based property*");
+ case PROP_CEE_ALL_JSON:
+ return UCHAR_CONSTANT("$!all-json");
default:
return UCHAR_CONSTANT("*invalid property id*");
}
@@ -707,6 +716,7 @@ static inline rsRetVal msgBaseConstruct(msg_t **ppThis)
pM->pRcvFromIP = NULL;
pM->rcvFrom.pRcvFrom = NULL;
pM->pRuleset = NULL;
+ pM->event = NULL;
memset(&pM->tRcvdAt, 0, sizeof(pM->tRcvdAt));
memset(&pM->tTIMESTAMP, 0, sizeof(pM->tTIMESTAMP));
pM->TAG.pszTAG = NULL;
@@ -833,6 +843,8 @@ CODESTARTobjDestruct(msg)
rsCStrDestruct(&pThis->pCSPROCID);
if(pThis->pCSMSGID != NULL)
rsCStrDestruct(&pThis->pCSMSGID);
+ if(pThis->event != NULL)
+ ee_deleteEvent(pThis->event);
# ifndef HAVE_ATOMIC_BUILTINS
MsgUnlock(pThis);
# endif
@@ -1198,7 +1210,7 @@ char *getProtocolVersionString(msg_t *pM)
}
-static inline void
+void
getRawMsg(msg_t *pM, uchar **pBuf, int *piLen)
{
if(pM == NULL) {
@@ -2219,6 +2231,41 @@ static uchar *getNOW(eNOWType eNow)
#undef tmpBUFSIZE /* clean up */
+/* Get a CEE-Property from libee. This function probably should be
+ * placed somewhere else, but this smells like a big restructuring
+ * useful in any case. So for the time being, I'll simply leave the
+ * function here, as the context seems good enough. -- rgerhards, 2010-12-01
+ */
+static inline void
+getCEEPropVal(msg_t *pMsg, es_str_t *propName, uchar **pRes, int *buflen, unsigned short *pbMustBeFreed)
+{
+ struct ee_field *field;
+ es_str_t *str;
+
+ if(*pbMustBeFreed)
+ free(*pRes);
+ *pRes = NULL;
+
+ if(pMsg->event == NULL) goto finalize_it;
+ if((field = ee_getEventField(pMsg->event, propName)) == NULL)
+ goto finalize_it;
+ /* right now, we always extract data from the first field value. A reason for this
+ * is that as of now (2010-12-01) liblognorm never populates more than one ;)
+ */
+ if((str = ee_getFieldValueAsStr(field, 0)) == NULL) goto finalize_it;
+ *pRes = (unsigned char*) es_str2cstr(str, "#000");
+ es_deleteStr(str);
+ *buflen = (int) ustrlen(*pRes);
+ *pbMustBeFreed = 1;
+
+finalize_it:
+ if(*pRes == NULL) {
+ /* could not find any value, so set it to empty */
+ *pRes = (unsigned char*)"";
+ *pbMustBeFreed = 0;
+ }
+}
+
/* This function returns a string-representation of the
* requested message property. This is a generic function used
* to abstract properties so that these can be easier
@@ -2261,7 +2308,7 @@ static uchar *getNOW(eNOWType eNow)
*pPropLen = sizeof("**OUT OF MEMORY**") - 1; \
return(UCHAR_CONSTANT("**OUT OF MEMORY**"));}
uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
- propid_t propID, size_t *pPropLen,
+ propid_t propid, es_str_t *propName, size_t *pPropLen,
unsigned short *pbMustBeFreed)
{
uchar *pRes; /* result pointer */
@@ -2270,6 +2317,7 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
uchar *pBuf;
int iLen;
short iOffs;
+ es_str_t *str; /* for CEE handling, temp. string */
BEGINfunc
assert(pMsg != NULL);
@@ -2283,7 +2331,7 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
*pbMustBeFreed = 0;
- switch(propID) {
+ switch(propid) {
case PROP_MSG:
pRes = getMSG(pMsg);
bufLen = getMSGLen(pMsg);
@@ -2416,11 +2464,20 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
case PROP_SYS_MYHOSTNAME:
pRes = glbl.GetLocalHostName();
break;
+ case PROP_CEE_ALL_JSON:
+ ee_fmtEventToJSON(pMsg->event, &str);
+ pRes = (uchar*) es_str2cstr(str, "#000");
+ es_deleteStr(str);
+ *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
+ break;
+ case PROP_CEE:
+ getCEEPropVal(pMsg, propName, &pRes, &bufLen, pbMustBeFreed);
+ break;
default:
/* 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", propid);
*pbMustBeFreed = 0;
*pPropLen = sizeof("**INVALID PROPERTY NAME**") - 1;
return UCHAR_CONSTANT("**INVALID PROPERTY NAME**");
@@ -2428,6 +2485,7 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
/* If we did not receive a template pointer, we are already done... */
if(pTpe == NULL) {
+ *pPropLen = (bufLen == -1) ? ustrlen(pRes) : bufLen;
return pRes;
}
@@ -3016,6 +3074,61 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
}
+/* The function returns a cee variable suitable for use with RainerScript. Most importantly, this means
+ * that the value is returned in a var_t object. The var_t is constructed inside this function and
+ * MUST be freed by the caller.
+ * 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
+ */
+rsRetVal
+msgGetCEEVar(msg_t *pMsg, cstr_t *propName, var_t **ppVar)
+{
+ DEFiRet;
+ var_t *pVar;
+ cstr_t *pstrProp;
+ es_str_t *str = NULL;
+ es_str_t *epropName = NULL;
+ struct ee_field *field;
+
+ ISOBJ_TYPE_assert(pMsg, msg);
+ ASSERT(propName != NULL);
+ ASSERT(ppVar != NULL);
+
+ /* make sure we have a var_t instance */
+ CHKiRet(var.Construct(&pVar));
+ CHKiRet(var.ConstructFinalize(pVar));
+
+ epropName = es_newStrFromBuf((char*)propName->pBuf, propName->iStrLen);
+ if((field = ee_getEventField(pMsg->event, epropName)) != NULL) {
+ /* right now, we always extract data from the first field value. A reason for this
+ * is that as of now (2010-12-01) liblognorm never populates more than one ;)
+ */
+ str = ee_getFieldValueAsStr(field, 0);
+ }
+
+ if(str == NULL) {
+ CHKiRet(cstrConstruct(&pstrProp));
+ CHKiRet(cstrFinalize(pstrProp));
+ } else {
+ CHKiRet(cstrConstructFromESStr(&pstrProp, str));
+ }
+
+ /* now create a string object out of it and hand that over to the var */
+ CHKiRet(var.SetString(pVar, pstrProp));
+ es_deleteStr(str);
+
+ /* finally store var */
+ *ppVar = pVar;
+
+finalize_it:
+ if(epropName != NULL)
+ es_deleteStr(epropName);
+ RETiRet;
+}
+
+
/* The returns a message variable suitable for use with RainerScript. Most importantly, this means
* that the value is returned in a var_t object. The var_t is constructed inside this function and
* MUST be freed by the caller.
@@ -3043,7 +3156,7 @@ msgGetMsgVar(msg_t *pThis, cstr_t *pstrPropName, var_t **ppVar)
/* always call MsgGetProp() without a template specifier */
/* TODO: optimize propNameToID() call -- rgerhards, 2009-06-26 */
propNameToID(pstrPropName, &propid);
- pszProp = (uchar*) MsgGetProp(pThis, NULL, propid, &propLen, &bMustBeFreed);
+ pszProp = (uchar*) MsgGetProp(pThis, NULL, propid, NULL, &propLen, &bMustBeFreed);
/* now create a string object out of it and hand that over to the var */
CHKiRet(rsCStrConstructFromszStr(&pstrProp, pszProp));
@@ -3058,6 +3171,8 @@ finalize_it:
RETiRet;
}
+
+
/* 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
diff --git a/runtime/msg.h b/runtime/msg.h
index 4897959c..1fd95994 100644
--- a/runtime/msg.h
+++ b/runtime/msg.h
@@ -29,10 +29,12 @@
#define MSG_H_INCLUDED 1
#include <pthread.h>
+#include <libestr.h>
#include "obj.h"
#include "syslogd-types.h"
#include "template.h"
#include "atomic.h"
+#include "libee/libee.h"
/* rgerhards 2004-11-08: The following structure represents a
@@ -105,6 +107,7 @@ struct msg {
it obviously is solved in way or another...). */
struct syslogTime tRcvdAt;/* time the message entered this program */
struct syslogTime tTIMESTAMP;/* (parsed) value of the timestamp */
+ struct ee_event *event; /**< libee event */
/* some fixed-size buffers to save malloc()/free() for frequently used fields (from the default templates) */
uchar szRawMsg[CONF_RAWMSG_BUFSIZE]; /* most messages are small, and these are stored here (without malloc/free!) */
uchar szHOSTNAME[CONF_HOSTNAME_BUFSIZE];
@@ -162,7 +165,8 @@ 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, size_t *pPropLen, unsigned short *pbMustBeFreed);
+ propid_t propid, es_str_t *propName,
+ size_t *pPropLen, unsigned short *pbMustBeFreed);
char *textpri(char *pRes, size_t pResLen, int pri);
rsRetVal msgGetMsgVar(msg_t *pThis, cstr_t *pstrPropName, var_t **ppVar);
rsRetVal MsgEnableThreadSafety(void);
@@ -170,6 +174,8 @@ 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);
/* TODO: remove these five (so far used in action.c) */
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index c2f6463c..17b20de2 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -136,6 +136,8 @@ typedef uintTiny propid_t;
#define PROP_SYS_QHOUR 156
#define PROP_SYS_MINUTE 157
#define PROP_SYS_MYHOSTNAME 158
+#define PROP_CEE 200
+#define PROP_CEE_ALL_JSON 201
/* The error codes below are orginally "borrowed" from
@@ -346,6 +348,9 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
RS_RET_FILE_NOT_SPECIFIED = -2180, /**< file name not configured where this was required */
RS_RET_INVLD_CONF_OBJ= -2200, /**< invalid config object (e.g. $Begin conf statement) */
+ RS_RET_ERR_LIBEE_INIT = -2201, /**< cannot obtain libee ctx */
+ RS_RET_ERR_LIBLOGNORM_INIT = -2202,/**< cannot obtain liblognorm ctx */
+ RS_RET_ERR_LIBLOGNORM_SAMPDB_LOAD = -2203,/**< liblognorm sampledb load failed */
/* RainerScript error messages (range 1000.. 1999) */
RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */
diff --git a/runtime/rule.c b/runtime/rule.c
index 42773768..fc1ee17c 100644
--- a/runtime/rule.c
+++ b/runtime/rule.c
@@ -70,6 +70,12 @@ getFIOPName(unsigned iFIOP)
case FIOP_REGEX:
pRet = "regex";
break;
+ case FIOP_EREREGEX:
+ pRet = "ereregex";
+ break;
+ case FIOP_ISEMPTY:
+ pRet = "isempty";
+ break;
default:
pRet = "NOP";
break;
@@ -190,7 +196,8 @@ dbgprintf("testing filter, f_pmask %d\n", pRule->f_filterData.f_pmask[pMsg->iFac
bRet = (pResult->val.num) ? 1 : 0;
} else {
assert(pRule->f_filter_type == FILTER_PROP); /* assert() just in case... */
- pszPropVal = MsgGetProp(pMsg, NULL, pRule->f_filterData.prop.propID, &propLen, &pbMustBeFreed);
+ pszPropVal = MsgGetProp(pMsg, NULL, pRule->f_filterData.prop.propID,
+ pRule->f_filterData.prop.propName, &propLen, &pbMustBeFreed);
/* Now do the compares (short list currently ;)) */
switch(pRule->f_filterData.prop.operation ) {
@@ -198,6 +205,10 @@ dbgprintf("testing filter, f_pmask %d\n", pRule->f_filterData.f_pmask[pMsg->iFac
if(rsCStrLocateInSzStr(pRule->f_filterData.prop.pCSCompValue, (uchar*) pszPropVal) != -1)
bRet = 1;
break;
+ case FIOP_ISEMPTY:
+ if(propLen == 0)
+ bRet = 1; /* process message! */
+ break;
case FIOP_ISEQUAL:
if(rsCStrSzStrCmp(pRule->f_filterData.prop.pCSCompValue,
pszPropVal, ustrlen(pszPropVal)) == 0)
@@ -230,14 +241,28 @@ dbgprintf("testing filter, f_pmask %d\n", pRule->f_filterData.f_pmask[pMsg->iFac
bRet = (bRet == 1) ? 0 : 1;
if(Debug) {
- dbgprintf("Filter: check for property '%s' (value '%s') ",
- propIDToName(pRule->f_filterData.prop.propID), pszPropVal);
+ char *cstr;
+ if(pRule->f_filterData.prop.propID == PROP_CEE) {
+ cstr = es_str2cstr(pRule->f_filterData.prop.propName, NULL);
+ dbgprintf("Filter: check for CEE property '%s' (value '%s') ",
+ cstr, pszPropVal);
+ free(cstr);
+ } else {
+ dbgprintf("Filter: check for property '%s' (value '%s') ",
+ propIDToName(pRule->f_filterData.prop.propID), pszPropVal);
+ }
if(pRule->f_filterData.prop.isNegated)
dbgprintf("NOT ");
- dbgprintf("%s '%s': %s\n",
- getFIOPName(pRule->f_filterData.prop.operation),
- rsCStrGetSzStrNoNULL(pRule->f_filterData.prop.pCSCompValue),
- bRet ? "TRUE" : "FALSE");
+ if(pRule->f_filterData.prop.operation == FIOP_ISEMPTY) {
+ dbgprintf("%s : %s\n",
+ getFIOPName(pRule->f_filterData.prop.operation),
+ bRet ? "TRUE" : "FALSE");
+ } else {
+ dbgprintf("%s '%s': %s\n",
+ getFIOPName(pRule->f_filterData.prop.operation),
+ rsCStrGetSzStrNoNULL(pRule->f_filterData.prop.pCSCompValue),
+ bRet ? "TRUE" : "FALSE");
+ }
}
/* cleanup */
@@ -324,6 +349,8 @@ CODESTARTobjDestruct(rule)
rsCStrDestruct(&pThis->f_filterData.prop.pCSCompValue);
if(pThis->f_filterData.prop.regex_cache != NULL)
rsCStrRegexDestruct(&pThis->f_filterData.prop.regex_cache);
+ if(pThis->f_filterData.prop.propName != NULL)
+ es_deleteStr(pThis->f_filterData.prop.propName);
} else if(pThis->f_filter_type == FILTER_EXPR) {
if(pThis->f_filterData.f_expr != NULL)
expr.Destruct(&pThis->f_filterData.f_expr);
@@ -368,6 +395,7 @@ DEFFUNC_llExecFunc(dbgPrintInitInfoAction)
/* debugprint for the rule object */
BEGINobjDebugPrint(rule) /* be sure to specify the object type also in END and CODESTART macros! */
int i;
+ char *cstr;
CODESTARTobjDebugPrint(rule)
dbgoprint((obj_t*) pThis, "rsyslog rule:\n");
if(pThis->pCSProgNameComp != NULL)
@@ -388,12 +416,19 @@ CODESTARTobjDebugPrint(rule)
} else {
dbgprintf("PROPERTY-BASED Filter:\n");
dbgprintf("\tProperty.: '%s'\n", propIDToName(pThis->f_filterData.prop.propID));
+ if(pThis->f_filterData.prop.propName != NULL) {
+ cstr = es_str2cstr(pThis->f_filterData.prop.propName, NULL);
+ dbgprintf("\tCEE-Prop.: '%s'\n", cstr);
+ free(cstr);
+ }
dbgprintf("\tOperation: ");
if(pThis->f_filterData.prop.isNegated)
dbgprintf("NOT ");
dbgprintf("'%s'\n", getFIOPName(pThis->f_filterData.prop.operation));
- dbgprintf("\tValue....: '%s'\n",
- rsCStrGetSzStrNoNULL(pThis->f_filterData.prop.pCSCompValue));
+ if(pThis->f_filterData.prop.pCSCompValue != NULL) {
+ dbgprintf("\tValue....: '%s'\n",
+ rsCStrGetSzStrNoNULL(pThis->f_filterData.prop.pCSCompValue));
+ }
dbgprintf("\tAction...: ");
}
diff --git a/runtime/rule.h b/runtime/rule.h
index 309a2ed8..3b34e11a 100644
--- a/runtime/rule.h
+++ b/runtime/rule.h
@@ -25,6 +25,7 @@
#ifndef INCLUDED_RULE_H
#define INCLUDED_RULE_H
+#include "libestr.h"
#include "linkedlist.h"
#include "regexp.h"
#include "expr.h"
@@ -49,6 +50,7 @@ struct rule_s {
cstr_t *pCSCompValue; /* value to "compare" against */
sbool isNegated;
propid_t propID; /* ID of the requested property */
+ es_str_t *propName; /* name of property for CEE-based filters */
} prop;
expr_t *f_expr; /* expression object */
} f_filterData;
diff --git a/runtime/stringbuf.c b/runtime/stringbuf.c
index ccf115c1..f4a9caae 100644
--- a/runtime/stringbuf.c
+++ b/runtime/stringbuf.c
@@ -35,6 +35,7 @@
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
+#include <libestr.h>
#include "rsyslog.h"
#include "stringbuf.h"
#include "srUtils.h"
@@ -104,6 +105,34 @@ finalize_it:
RETiRet;
}
+
+/* construct from es_str_t string
+ * rgerhards 2010-12-03
+ */
+rsRetVal cstrConstructFromESStr(cstr_t **ppThis, es_str_t *str)
+{
+ DEFiRet;
+ cstr_t *pThis;
+
+ assert(ppThis != NULL);
+
+ CHKiRet(rsCStrConstruct(&pThis));
+
+ pThis->iBufSize = pThis->iStrLen = es_strlen(str);
+ if((pThis->pBuf = (uchar*) MALLOC(sizeof(uchar) * pThis->iStrLen)) == NULL) {
+ RSFREEOBJ(pThis);
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ /* we do NOT need to copy the \0! */
+ memcpy(pThis->pBuf, es_getBufAddr(str), pThis->iStrLen);
+
+ *ppThis = pThis;
+
+finalize_it:
+ RETiRet;
+}
+
/* construct from CStr object. only the counted string is
* copied, not the szString.
* rgerhards 2005-10-18
diff --git a/runtime/stringbuf.h b/runtime/stringbuf.h
index c5130238..df234012 100644
--- a/runtime/stringbuf.h
+++ b/runtime/stringbuf.h
@@ -36,6 +36,7 @@
#define _STRINGBUF_H_INCLUDED__ 1
#include <assert.h>
+#include <libestr.h>
/**
* The dynamic string buffer object.
@@ -57,6 +58,7 @@ typedef struct cstr_s
*/
rsRetVal cstrConstruct(cstr_t **ppThis);
#define rsCStrConstruct(x) cstrConstruct((x))
+rsRetVal cstrConstructFromESStr(cstr_t **ppThis, es_str_t *str);
rsRetVal rsCStrConstructFromszStr(cstr_t **ppThis, uchar *sz);
rsRetVal rsCStrConstructFromCStr(cstr_t **ppThis, cstr_t *pFrom);
diff --git a/runtime/typedefs.h b/runtime/typedefs.h
index 38bc02d5..1f624f7a 100644
--- a/runtime/typedefs.h
+++ b/runtime/typedefs.h
@@ -127,7 +127,8 @@ typedef enum {
FIOP_ISEQUAL = 2, /* is (exactly) equal? */
FIOP_STARTSWITH = 3, /* starts with a string? */
FIOP_REGEX = 4, /* matches a (BRE) regular expression? */
- FIOP_EREREGEX = 5 /* matches a ERE regular expression? */
+ FIOP_EREREGEX = 5, /* matches a ERE regular expression? */
+ FIOP_ISEMPTY = 6 /* string empty <=> strlen(s) == 0 ?*/
} fiop_t;
/* types of configuration handlers
diff --git a/runtime/var.h b/runtime/var.h
index 6d890ec9..ae971bb5 100644
--- a/runtime/var.h
+++ b/runtime/var.h
@@ -40,6 +40,7 @@ typedef struct var_s {
varType_t varType;
union {
number_t num;
+ es_str_t *str;
cstr_t *pStr;
syslogTime_t vSyslogTime;
diff --git a/runtime/vm.c b/runtime/vm.c
index 0ed174d1..c5521c31 100644
--- a/runtime/vm.c
+++ b/runtime/vm.c
@@ -448,6 +448,7 @@ BEGINop(PUSHMSGVAR) /* remember to set the instruction also in the ENDop macro!
var_t *pVal; /* the value to push */
cstr_t *pstrVal;
CODESTARTop(PUSHMSGVAR)
+dbgprintf("XXX: pushMSGVAR, var '%s'\n", rsCStrGetSzStr(pOp->operand.pVar->val.pStr));
if(pThis->pMsg == NULL) {
/* TODO: flag an error message! As a work-around, we permit
* execution to continue here with an empty string
@@ -468,6 +469,31 @@ finalize_it:
ENDop(PUSHMSGVAR)
+BEGINop(PUSHCEEVAR) /* remember to set the instruction also in the ENDop macro! */
+ var_t *pVal; /* the value to push */
+ cstr_t *pstrVal;
+CODESTARTop(PUSHCEEVAR)
+dbgprintf("XXX: pushCEEVAR, var '%s'\n", rsCStrGetSzStr(pOp->operand.pVar->val.pStr));
+ if(pThis->pMsg == NULL) {
+ /* TODO: flag an error message! As a work-around, we permit
+ * execution to continue here with an empty string
+ */
+ CHKiRet(var.Construct(&pVal));
+ CHKiRet(var.ConstructFinalize(pVal));
+ CHKiRet(rsCStrConstructFromszStr(&pstrVal, (uchar*)""));
+ CHKiRet(var.SetString(pVal, pstrVal));
+ } else {
+ /* we have a message, so pull value from there */
+ CHKiRet(msgGetCEEVar(pThis->pMsg, pOp->operand.pVar->val.pStr, &pVal));
+ }
+
+ /* if we reach this point, we have a valid pVal and can push it */
+ vmstk.Push(pThis->pStk, pVal);
+dbgprintf("XXX: pushCEEVAR, result '%s'\n", rsCStrGetSzStr(pVal->val.pStr));
+finalize_it:
+ENDop(PUSHCEEVAR)
+
+
BEGINop(PUSHSYSVAR) /* remember to set the instruction also in the ENDop macro! */
var_t *pVal; /* the value to push */
CODESTARTop(PUSHSYSVAR)
@@ -685,6 +711,7 @@ execProg(vm_t *pThis, vmprg_t *pProg)
doOP(NOT);
doOP(PUSHCONSTANT);
doOP(PUSHMSGVAR);
+ doOP(PUSHCEEVAR);
doOP(PUSHSYSVAR);
doOP(STRADD);
doOP(PLUS);
diff --git a/runtime/vmop.h b/runtime/vmop.h
index 67048c26..c085a940 100644
--- a/runtime/vmop.h
+++ b/runtime/vmop.h
@@ -59,6 +59,7 @@ typedef enum { /* do NOT start at 0 to detect uninitialized types after calloc(
opcode_PUSHSYSVAR = 1001, /* requires var operand */
opcode_PUSHMSGVAR = 1002, /* requires var operand */
opcode_PUSHCONSTANT = 1003, /* requires var operand */
+ opcode_PUSHCEEVAR = 1004, /* requires var operand */
opcode_UNARY_MINUS = 1010,
opcode_FUNC_CALL = 1012,
opcode_END_PROG = 2000