diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2013-07-22 17:38:31 +0200 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2013-07-22 17:38:31 +0200 |
commit | 4ecd6bb9462f0fbaf4609f62d768847cc7e85f7e (patch) | |
tree | 1babe4c6a8c878dbfb81ae02083e2ca66b373566 | |
parent | 5721c4dff691503a28704155132ccba67361c202 (diff) | |
download | rsyslog-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.l | 2 | ||||
-rw-r--r-- | runtime/msg.c | 42 | ||||
-rw-r--r-- | runtime/msg.h | 2 | ||||
-rw-r--r-- | runtime/rsyslog.h | 1 | ||||
-rw-r--r-- | runtime/ruleset.c | 5 | ||||
-rw-r--r-- | template.c | 26 |
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); @@ -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: |