summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--grammar/rainerscript.c24
-rw-r--r--runtime/msg.c42
-rw-r--r--runtime/msg.h1
-rw-r--r--runtime/rsconf.c99
4 files changed, 161 insertions, 5 deletions
diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c
index 0def9653..91e71e97 100644
--- a/grammar/rainerscript.c
+++ b/grammar/rainerscript.c
@@ -285,6 +285,7 @@ done:
return expr;
}
+
/* ensure that retval is a number; if string is no number,
* try to convert it to one. The semantics from es_str2num()
* are used (bSuccess tells if the conversion went well or not).
@@ -315,21 +316,28 @@ exprret2String(struct exprret *r, int *bMustFree)
return r->d.estr;
}
+#define FREE_BOTH_RET \
+ if(r.datatype == 'S') es_deleteStr(r.d.estr); \
+ if(l.datatype == 'S') es_deleteStr(l.d.estr)
+
#define COMP_NUM_BINOP(x) \
cnfexprEval(expr->l, &l, usrptr); \
cnfexprEval(expr->r, &r, usrptr); \
ret->datatype = 'N'; \
- ret->d.n = exprret2Number(&l, &convok_l) x exprret2Number(&r, &convok_r)
+ ret->d.n = exprret2Number(&l, &convok_l) x exprret2Number(&r, &convok_r); \
+ FREE_BOTH_RET
#define PREP_TWO_STRINGS \
cnfexprEval(expr->l, &l, usrptr); \
cnfexprEval(expr->r, &r, usrptr); \
estr_r = exprret2String(&r, &bMustFree); \
- estr_l = exprret2String(&l, &bMustFree2)
+ estr_l = exprret2String(&l, &bMustFree2); \
+ FREE_BOTH_RET
#define FREE_TWO_STRINGS \
if(bMustFree) es_deleteStr(estr_r); \
- if(bMustFree2) es_deleteStr(estr_l)
+ if(bMustFree2) es_deleteStr(estr_l); \
+ FREE_BOTH_RET
/* evaluate an expression.
* Note that we try to avoid malloc whenever possible (because of
@@ -386,6 +394,7 @@ cnfexprEval(struct cnfexpr *expr, struct exprret *ret, void* usrptr)
ret->d.n = (l.d.n == r.d.n); /*CMP*/
}
}
+ FREE_BOTH_RET;
break;
case CMP_NE:
cnfexprEval(expr->l, &l, usrptr);
@@ -418,6 +427,7 @@ cnfexprEval(struct cnfexpr *expr, struct exprret *ret, void* usrptr)
ret->d.n = (l.d.n != r.d.n); /*CMP*/
}
}
+ FREE_BOTH_RET;
break;
case CMP_LE:
cnfexprEval(expr->l, &l, usrptr);
@@ -450,6 +460,7 @@ cnfexprEval(struct cnfexpr *expr, struct exprret *ret, void* usrptr)
ret->d.n = (l.d.n <= r.d.n); /*CMP*/
}
}
+ FREE_BOTH_RET;
break;
case CMP_GE:
cnfexprEval(expr->l, &l, usrptr);
@@ -482,6 +493,7 @@ cnfexprEval(struct cnfexpr *expr, struct exprret *ret, void* usrptr)
ret->d.n = (l.d.n >= r.d.n); /*CMP*/
}
}
+ FREE_BOTH_RET;
break;
case CMP_LT:
cnfexprEval(expr->l, &l, usrptr);
@@ -514,6 +526,7 @@ cnfexprEval(struct cnfexpr *expr, struct exprret *ret, void* usrptr)
ret->d.n = (l.d.n < r.d.n); /*CMP*/
}
}
+ FREE_BOTH_RET;
break;
case CMP_GT:
cnfexprEval(expr->l, &l, usrptr);
@@ -546,6 +559,7 @@ cnfexprEval(struct cnfexpr *expr, struct exprret *ret, void* usrptr)
ret->d.n = (l.d.n > r.d.n); /*CMP*/
}
}
+ FREE_BOTH_RET;
break;
case CMP_STARTSWITH:
PREP_TWO_STRINGS;
@@ -583,6 +597,7 @@ cnfexprEval(struct cnfexpr *expr, struct exprret *ret, void* usrptr)
else
ret->d.n = 0ll;
}
+ FREE_BOTH_RET;
break;
case AND:
cnfexprEval(expr->l, &l, usrptr);
@@ -596,11 +611,13 @@ cnfexprEval(struct cnfexpr *expr, struct exprret *ret, void* usrptr)
} else {
ret->d.n = 0ll;
}
+ FREE_BOTH_RET;
break;
case NOT:
cnfexprEval(expr->r, &r, usrptr);
ret->datatype = 'N';
ret->d.n = !exprret2Number(&r, &convok_r);
+ if(r.datatype == 'S') es_deleteStr(r.d.estr);
break;
case 'N':
ret->datatype = 'N';
@@ -633,6 +650,7 @@ cnfexprEval(struct cnfexpr *expr, struct exprret *ret, void* usrptr)
cnfexprEval(expr->r, &r, usrptr);
ret->datatype = 'N';
ret->d.n = -exprret2Number(&r, &convok_r);
+ if(r.datatype == 'S') es_deleteStr(r.d.estr);
break;
default:
ret->datatype = 'N';
diff --git a/runtime/msg.c b/runtime/msg.c
index 96fe1b2c..4e96a02f 100644
--- a/runtime/msg.c
+++ b/runtime/msg.c
@@ -3116,9 +3116,51 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
* to rewrite the script engine as well!
* rgerhards, 2010-12-03
*/
+es_str_t*
+msgGetCEEVarNew(msg_t *pMsg, char *name)
+{
+ es_str_t *estr = NULL;
+ es_str_t *epropName = NULL;
+ struct ee_field *field;
+
+ ISOBJ_TYPE_assert(pMsg, msg);
+
+ if(pMsg->event == NULL) {
+ estr = es_newStr(1);
+ goto done;
+ }
+
+ epropName = es_newStrFromCStr(name, strlen(name)); // TODO: optimize (in grammar!)
+dbgprintf("ZZZZ: pmsg->event %p\n", pMsg->event);
+ field = ee_getEventField(pMsg->event, epropName);
+ if(field != NULL) {
+ estr = ee_getFieldValueAsStr(field, 0);
+ }
+ if(estr == NULL) {
+ DBGPRINTF("msgGetCEEVar: error obtaining var (field=%p, var='%s')\n",
+ field, name);
+ estr = es_newStrFromCStr("*ERROR*", sizeof("*ERROR*") - 1);
+ }
+ es_deleteStr(epropName);
+
+done:
+ return estr;
+}
+
+
+/* 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)
{
+#warning remove as part of cleanup
DEFiRet;
var_t *pVar;
cstr_t *pstrProp;
diff --git a/runtime/msg.h b/runtime/msg.h
index 19debb03..55d2dfc0 100644
--- a/runtime/msg.h
+++ b/runtime/msg.h
@@ -178,6 +178,7 @@ 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);
/* TODO: remove these five (so far used in action.c) */
diff --git a/runtime/rsconf.c b/runtime/rsconf.c
index c1bc3b72..d12a258b 100644
--- a/runtime/rsconf.c
+++ b/runtime/rsconf.c
@@ -65,6 +65,7 @@
#include "parser.h"
#include "outchannel.h"
#include "threads.h"
+#include "datetime.h"
#include "parserif.h"
#include "dirty.h"
@@ -77,6 +78,7 @@ DEFobjCurrIf(conf)
DEFobjCurrIf(errmsg)
DEFobjCurrIf(glbl)
DEFobjCurrIf(parser)
+DEFobjCurrIf(datetime)
/* exported static data */
rsconf_t *runConf = NULL;/* the currently running config */
@@ -244,6 +246,87 @@ cnfDoActlst(struct cnfactlst *actlst, rule_t *pRule)
RETiRet;
}
+/* 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;
+ }
+
+ /* 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;
+}
/*------------------------------ interface to flex/bison parser ------------------------------*/
extern int yylineno;
@@ -350,9 +433,19 @@ es_str_t*
cnfGetVar(char *name, void *usrptr)
{
es_str_t *estr;
- dbgprintf("ZZZZ: var '%s' requested\n", name);
if(name[0] == '$') {
- estr = msgGetMsgVarNew((msg_t*) usrptr, (uchar*)name+1);
+ 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+1);
+ }
+ if(Debug) {
+ char *s;
+ s = es_str2cstr(estr, NULL);
+ dbgprintf("rainerscript: var '%s': '%s'\n", name, s);
+ free(s);
}
return estr;
}
@@ -1258,6 +1351,7 @@ BEGINObjClassInit(rsconf, 1, OBJ_IS_CORE_MODULE) /* class, version */
CHKiRet(objUse(conf, CORE_COMPONENT));
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
CHKiRet(objUse(parser, CORE_COMPONENT));
/* now set our own handlers */
@@ -1275,6 +1369,7 @@ BEGINObjClassExit(rsconf, OBJ_IS_CORE_MODULE) /* class, version */
objRelease(conf, CORE_COMPONENT);
objRelease(errmsg, CORE_COMPONENT);
objRelease(glbl, CORE_COMPONENT);
+ objRelease(datetime, CORE_COMPONENT);
objRelease(parser, CORE_COMPONENT);
ENDObjClassExit(rsconf)