summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2013-07-22 17:38:31 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2013-07-22 17:38:31 +0200
commit4ecd6bb9462f0fbaf4609f62d768847cc7e85f7e (patch)
tree1babe4c6a8c878dbfb81ae02083e2ca66b373566
parent5721c4dff691503a28704155132ccba67361c202 (diff)
downloadrsyslog-4ecd6bb9462f0fbaf4609f62d768847cc7e85f7e.tar.gz
rsyslog-4ecd6bb9462f0fbaf4609f62d768847cc7e85f7e.tar.bz2
rsyslog-4ecd6bb9462f0fbaf4609f62d768847cc7e85f7e.zip
first shot at global variables (without proper sync so far)
-rw-r--r--grammar/lexer.l2
-rw-r--r--runtime/msg.c42
-rw-r--r--runtime/msg.h2
-rw-r--r--runtime/rsyslog.h1
-rw-r--r--runtime/ruleset.c5
-rw-r--r--template.c26
6 files changed, 64 insertions, 14 deletions
diff --git a/grammar/lexer.l b/grammar/lexer.l
index 44606977..438ccdd8 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); 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/runtime/msg.c b/runtime/msg.c
index 73fa0367..87213bb7 100644
--- a/runtime/msg.c
+++ b/runtime/msg.c
@@ -66,6 +66,11 @@
#include "var.h"
#include "rsconf.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
+ */
+struct json_object *global_var_root = NULL;
+
/* static data */
DEFobjStaticHelpers
DEFobjCurrIf(datetime)
@@ -539,6 +544,8 @@ propNameStrToID(uchar *pName, propid_t *pPropID)
*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")) {
@@ -639,6 +646,8 @@ 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:
@@ -2584,6 +2593,12 @@ getLocalVarPropVal(msg_t *pM, es_str_t *propName, uchar **pRes, rs_size_t *bufle
return getJSONPropVal(pM->localvars, propName, pRes, buflen, pbMustBeFreed);
}
+rsRetVal
+getGlobalVarPropVal( es_str_t *propName, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed)
+{
+ return getJSONPropVal(global_var_root, propName, pRes, buflen, pbMustBeFreed);
+}
+
/* Get a JSON-based-variable as native json object */
rsRetVal
@@ -2628,6 +2643,12 @@ 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)
+{
+ return msgGetJSONPropJSON(global_var_root, propName, pjson);
+}
+
/* Encode a JSON value and add it to provided string. Note that
* the string object may be NULL. In this case, it is created
* if and only if escaping is needed.
@@ -3028,6 +3049,9 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
case PROP_LOCAL_VAR:
getLocalVarPropVal(pMsg, propName, &pRes, &bufLen, pbMustBeFreed);
break;
+ case PROP_GLOBAL_VAR:
+ getGlobalVarPropVal(propName, &pRes, &bufLen, pbMustBeFreed);
+ break;
case PROP_SYS_BOM:
if(*pbMustBeFreed == 1)
free(pRes);
@@ -3869,13 +3893,13 @@ jsonPathGetLeaf(uchar *name, int lenName)
int i;
for(i = lenName ; i >= 0 ; --i)
if(i == 0) {
- if(name[0] == '.' || name[0] == '!')
+ if(name[0] == '!' || name[0] == '.' || name[0] == '/')
break;
} else {
if(name[i] == '!')
break;
}
- if(name[i] == '!' || name[i] == '.')
+ if(name[i] == '!' || name[i] == '.' || name[i] == '/')
++i;
return name + i;
}
@@ -3891,9 +3915,9 @@ jsonPathFindNext(struct json_object *root, uchar *namestart, uchar **name, uchar
uchar *p = *name;
DEFiRet;
- if(*p == '!' || (*name == namestart && *p == '.'))
+ if(*p == '!' || (*name == namestart && (*p == '.' || *p == '/')))
++p;
- for(i = 0 ; *p && !(p == namestart && *p == '.') && *p != '!' && p != leaf && i < sizeof(namebuf)-1 ; ++i, ++p)
+ for(i = 0 ; *p && !(p == namestart && (*p == '.' || *p == '/')) && *p != '!' && p != leaf && i < sizeof(namebuf)-1 ; ++i, ++p)
namebuf[i] = *p;
if(i > 0) {
namebuf[i] = '\0';
@@ -3988,7 +4012,7 @@ msgAddJSONObj(msg_t *pM, uchar *name, struct json_object *json, struct json_obje
DEFiRet;
MsgLock(pM);
- if((name[0] == '!' || name[0] == '.') && name[1] == '\0') {
+ if((name[0] == '!' || name[0] == '.' || name[0] == '/') && name[1] == '\0') {
if(*pjroot == NULL)
*pjroot = json;
else
@@ -4049,7 +4073,7 @@ msgDelJSONVar(msg_t *pM, struct json_object **jroot, uchar *name)
dbgprintf("AAAA: unset variable '%s'\n", name);
MsgLock(pM);
- if((name[0] == '!' || name[0] == '.') && name[1] == '\0') {
+ if((name[0] == '!' || name[0] == '.' || name[0] == '/') && name[1] == '\0') {
/* strange, but I think we should permit this. After all,
* we trust rsyslog.conf to be written by the admin.
*/
@@ -4157,10 +4181,12 @@ msgSetJSONFromVar(msg_t *pMsg, uchar *varname, struct var *v)
ABORT_FINALIZE(RS_RET_ERR);
}
/* we always know strlen(varname) > 2 */
+ if(varname[1] == '!')
+ msgAddJSONObj(pMsg, varname+1, json, &pMsg->json);
if(varname[1] == '.')
msgAddJSONObj(pMsg, varname+1, json, &pMsg->localvars);
- else
- msgAddJSONObj(pMsg, varname+1, json, &pMsg->json);
+ else /* global - '/' */
+ msgAddJSONObj(pMsg, varname+1, json, &global_var_root);
finalize_it:
RETiRet;
}
diff --git a/runtime/msg.h b/runtime/msg.h
index f9ffc5e3..6b85042d 100644
--- a/runtime/msg.h
+++ b/runtime/msg.h
@@ -208,7 +208,9 @@ uchar *getRcvFrom(msg_t *pM);
rsRetVal propNameToID(cstr_t *pCSPropName, 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 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);
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index 9fd527fd..e51f11bd 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -146,6 +146,7 @@ typedef uintTiny propid_t;
#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
diff --git a/runtime/ruleset.c b/runtime/ruleset.c
index 6c4eae26..dae5bbaa 100644
--- a/runtime/ruleset.c
+++ b/runtime/ruleset.c
@@ -452,6 +452,11 @@ evalPROPFILT(struct cnfstmt *stmt, msg_t *pMsg)
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);
} else {
DBGPRINTF("Filter: check for property '%s' (value '%s') ",
propIDToName(stmt->d.s_propfilt.propID), pszPropVal);
diff --git a/template.c b/template.c
index 77e23863..8cb7bc27 100644
--- a/template.c
+++ b/template.c
@@ -367,6 +367,17 @@ 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_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,
@@ -808,8 +819,8 @@ do_Parameter(uchar **pp, struct template *pTpl)
cstrDestruct(&pStrProp);
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
- } else if(pTpe->data.field.propid == PROP_LOCAL_VAR) {
- /* in CEE case, we need to preserve the actual property name, but correct the root ID (bang vs. dot) */
+ } 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);
@@ -1112,7 +1123,8 @@ 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) {
+ if(pTpe->data.field.propid == PROP_CEE || pTpe->data.field.propid == PROP_LOCAL_VAR ||
+ pTpe->data.field.propid == PROP_GLOBAL_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;
@@ -1598,8 +1610,8 @@ createPropertyTpe(struct template *pTpl, struct cnfobj *o)
/* 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) {
- /* in this case, we need to preserve the actual property name, but correct the root ID (bang vs. dot) */
+ } 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 */
}
@@ -2114,6 +2126,10 @@ void tplPrintList(rsconf_t *conf)
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);
}
switch(pTpe->data.field.eDateFormat) {
case tplFmtDefault: