summaryrefslogtreecommitdiffstats
path: root/runtime/msg.c
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/msg.c')
-rw-r--r--runtime/msg.c379
1 files changed, 235 insertions, 144 deletions
diff --git a/runtime/msg.c b/runtime/msg.c
index 85f83502..5df4e031 100644
--- a/runtime/msg.c
+++ b/runtime/msg.c
@@ -65,6 +65,13 @@
#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
+ */
+static pthread_rwlock_t glblVars_rwlock;
+struct json_object *global_var_root = NULL;
/* static data */
DEFobjStaticHelpers
@@ -317,7 +324,7 @@ static pthread_mutex_t mutTrimCtr; /* mutex to handle malloc trim */
/* some forward declarations */
static int getAPPNAMELen(msg_t *pM, sbool bLockMutex);
-static rsRetVal jsonPathFindParent(msg_t *pM, uchar *name, uchar *leaf, struct json_object **parent, int bCreate);
+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);
@@ -445,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")) {
@@ -527,13 +532,18 @@ 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(!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;
iRet = RS_RET_VAR_NOT_FOUND;
}
@@ -542,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)
{
@@ -627,6 +622,8 @@ uchar *propIDToName(propid_t propID)
return UCHAR_CONSTANT("$MYHOSTNAME");
case PROP_CEE:
return UCHAR_CONSTANT("*CEE-based property*");
+ case PROP_LOCAL_VAR:
+ return UCHAR_CONSTANT("*LOCAL_VARIABLE*");
case PROP_CEE_ALL_JSON:
return UCHAR_CONSTANT("$!all-json");
case PROP_SYS_BOM:
@@ -701,6 +698,8 @@ static inline rsRetVal msgBaseConstruct(msg_t **ppThis)
pM->rcvFrom.pRcvFrom = NULL;
pM->pRuleset = NULL;
pM->json = NULL;
+ pM->localvars = NULL;
+ pM->dfltTZ[0] = '\0';
memset(&pM->tRcvdAt, 0, sizeof(pM->tRcvdAt));
memset(&pM->tTIMESTAMP, 0, sizeof(pM->tTIMESTAMP));
pM->TAG.pszTAG = NULL;
@@ -845,6 +844,8 @@ CODESTARTobjDestruct(msg)
rsCStrDestruct(&pThis->pCSMSGID);
if(pThis->json != NULL)
json_object_put(pThis->json);
+ if(pThis->localvars != NULL)
+ json_object_put(pThis->localvars);
if(pThis->pszUUID != NULL)
free(pThis->pszUUID);
# ifndef HAVE_ATOMIC_BUILTINS
@@ -999,6 +1000,8 @@ msg_t* MsgDup(msg_t* pOld)
if(pOld->json != NULL)
pNew->json = jsonDeepCopy(pOld->json);
+ if(pOld->localvars != NULL)
+ pNew->localvars = jsonDeepCopy(pOld->localvars);
/* we do not copy all other cache properties, as we do not even know
* if they are needed once again. So we let them re-create if needed.
@@ -1059,6 +1062,10 @@ static rsRetVal MsgSerialize(msg_t *pThis, strm_t *pStrm)
psz = (uchar*) json_object_get_string(pThis->json);
CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("json"), PROPTYPE_PSZ, (void*) psz));
}
+ if(pThis->localvars != NULL) {
+ psz = (uchar*) json_object_get_string(pThis->localvars);
+ CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("localvars"), PROPTYPE_PSZ, (void*) psz));
+ }
objSerializePTR(pStrm, pCSAPPNAME, CSTR);
objSerializePTR(pStrm, pCSPROCID, CSTR);
@@ -1200,6 +1207,14 @@ MsgDeserialize(msg_t *pMsg, strm_t *pStrm)
reinitVar(pVar);
CHKiRet(objDeserializeProperty(pVar, pStrm));
}
+ if(isProp("localvars")) {
+ tokener = json_tokener_new();
+ pMsg->localvars = json_tokener_parse_ex(tokener, (char*)rsCStrGetSzStrNoNULL(pVar->val.pStr),
+ cstrLen(pVar->val.pStr));
+ json_tokener_free(tokener);
+ reinitVar(pVar);
+ CHKiRet(objDeserializeProperty(pVar, pStrm));
+ }
if(isProp("pszStrucData")) {
MsgSetStructuredData(pMsg, (char*) rsCStrGetSzStrNoNULL(pVar->val.pStr));
reinitVar(pVar);
@@ -2198,6 +2213,15 @@ void MsgSetInputName(msg_t *pThis, prop_t *inputName)
pThis->pInputName = inputName;
}
+/* Set default TZ. Note that at most 7 chars are set, as we would
+ * otherwise overrun our buffer!
+ */
+void MsgSetDfltTZ(msg_t *pThis, char *tz)
+{
+ strncpy(pThis->dfltTZ, tz, 7);
+ pThis->dfltTZ[7] = '\0'; /* ensure 0-Term in case of overflow! */
+}
+
/* Set the pfrominet socket store, so that we can obtain the peer at some
* later time. Note that we do not check if pRcvFrom is already set, so this
@@ -2220,7 +2244,6 @@ finalize_it:
RETiRet;
}
-
/* rgerhards 2008-09-10: set RcvFrom name in msg object. This calls AddRef()
* on the property, because this must be done in all current cases and there
* is no case expected where this may not be necessary.
@@ -2446,11 +2469,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);
}
@@ -2493,12 +2522,12 @@ static uchar *getNOW(eNOWType eNow, struct syslogTime *t)
#undef tmpBUFSIZE /* clean up */
-/* Get a CEE-Property as string value*/
+/* Get a JSON-Property as string value (used for various types of JSON-based vars) */
rsRetVal
-getCEEPropVal(msg_t *pM, es_str_t *propName, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed)
+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;
@@ -2506,15 +2535,26 @@ getCEEPropVal(msg_t *pM, es_str_t *propName, uchar **pRes, rs_size_t *buflen, un
if(*pbMustBeFreed)
free(*pRes);
*pRes = NULL;
- // TODO: mutex?
- if(pM->json == NULL) goto finalize_it;
- if(!es_strbufcmp(propName, (uchar*)"!", 1)) {
- field = pM->json;
+ 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 {
- name = (uchar*)es_str2cstr(propName, NULL);
- leaf = jsonPathGetLeaf(name, ustrlen(name));
- CHKiRet(jsonPathFindParent(pM, name, leaf, &parent, 1));
+ DBGPRINTF("msgGetJSONPropVal; invalid property id %d\n",
+ pProp->id);
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+ if(jroot == NULL) goto finalize_it;
+
+ if(!strcmp((char*)pProp->name, "!")) {
+ field = jroot;
+ } else {
+ 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) {
@@ -2524,7 +2564,8 @@ getCEEPropVal(msg_t *pM, es_str_t *propName, uchar **pRes, rs_size_t *buflen, un
}
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*)"";
@@ -2534,35 +2575,47 @@ finalize_it:
}
-/* Get a CEE-Property as native json object
- */
+/* Get a JSON-based-variable as native json object */
rsRetVal
-msgGetCEEPropJSON(msg_t *pM, 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(pM->json == NULL) {
+ 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)) {
- *pjson = pM->json;
+ if(!strcmp((char*)pProp->name, "!")) {
+ *pjson = jroot;
FINALIZE;
}
- name = (uchar*)es_str2cstr(propName, NULL);
- leaf = jsonPathGetLeaf(name, ustrlen(name));
- CHKiRet(jsonPathFindParent(pM, 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;
}
@@ -2767,7 +2820,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 */
@@ -2790,7 +2843,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);
@@ -2962,7 +3015,9 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
}
break;
case PROP_CEE:
- getCEEPropVal(pMsg, propName, &pRes, &bufLen, pbMustBeFreed);
+ case PROP_LOCAL_VAR:
+ case PROP_GLOBAL_VAR:
+ getJSONPropVal(pMsg, pProp, &pRes, &bufLen, pbMustBeFreed);
break;
case PROP_SYS_BOM:
if(*pbMustBeFreed == 1)
@@ -3023,7 +3078,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**");
@@ -3631,66 +3686,6 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
}
-/* The function returns a cee 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
- */
-es_str_t*
-msgGetCEEVarNew(msg_t *pMsg, char *name)
-{
- uchar *leaf;
- char *val;
- es_str_t *estr = NULL;
- struct json_object *json, *parent;
-
- ISOBJ_TYPE_assert(pMsg, msg);
-
- if(pMsg->json == NULL) {
- estr = es_newStr(1);
- goto done;
- }
- leaf = jsonPathGetLeaf((uchar*)name, strlen(name));
- if(jsonPathFindParent(pMsg, (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;
-}
-
-
-/* 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;
-
- ISOBJ_TYPE_assert(pThis, msg);
-
- /* always call MsgGetProp() without a template specifier */
- /* TODO: optimize propNameToID() call -- rgerhards, 2009-06-26 */
- propNameStrToID(name, &propid);
- pszProp = (uchar*) MsgGetProp(pThis, NULL, propid, NULL, &propLen, &bMustBeFreed, NULL);
-
- 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
@@ -3792,16 +3787,22 @@ static uchar *
jsonPathGetLeaf(uchar *name, int lenName)
{
int i;
- for(i = lenName ; name[i] != '!' && i >= 0 ; --i)
- /* just skip */;
- if(name[i] == '!')
+ for(i = lenName ; i >= 0 ; --i)
+ if(i == 0) {
+ if(name[0] == '!' || name[0] == '.' || name[0] == '/')
+ break;
+ } else {
+ if(name[i] == '!')
+ break;
+ }
+ if(name[i] == '!' || name[i] == '.' || name[i] == '/')
++i;
return name + i;
}
static rsRetVal
-jsonPathFindNext(struct json_object *root, uchar **name, uchar *leaf,
+jsonPathFindNext(struct json_object *root, uchar *namestart, uchar **name, uchar *leaf,
struct json_object **found, int bCreate)
{
uchar namebuf[1024];
@@ -3810,9 +3811,9 @@ jsonPathFindNext(struct json_object *root, uchar **name, uchar *leaf,
uchar *p = *name;
DEFiRet;
- if(*p == '!')
+ if(*p == '!' || (*name == namestart && (*p == '.' || *p == '/')))
++p;
- for(i = 0 ; *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';
@@ -3836,12 +3837,14 @@ finalize_it:
}
static rsRetVal
-jsonPathFindParent(msg_t *pM, uchar *name, uchar *leaf, struct json_object **parent, int bCreate)
+jsonPathFindParent(struct json_object *jroot, uchar *name, uchar *leaf, struct json_object **parent, int bCreate)
{
+ uchar *namestart;
DEFiRet;
- *parent = pM->json;
+ namestart = name;
+ *parent = jroot;
while(name < leaf-1) {
- jsonPathFindNext(*parent, &name, leaf, parent, bCreate);
+ jsonPathFindNext(*parent, namestart, &name, leaf, parent, bCreate);
}
RETiRet;
}
@@ -3868,31 +3871,28 @@ DBGPRINTF("AAAA jsonMerge adds '%s'\n", it.key);
/* find a JSON structure element (field or container doesn't matter). */
rsRetVal
-jsonFind(msg_t *pM, 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;
DEFiRet;
- if(pM->json == NULL) {
+ if(jroot == NULL) {
field = NULL;
goto finalize_it;
}
- if(!es_strbufcmp(propName, (uchar*)"!", 1)) {
- field = pM->json;
+ if(!strcmp((char*)pProp->name, "!")) {
+ field = jroot;
} else {
- name = (uchar*)es_str2cstr(propName, NULL);
- leaf = jsonPathGetLeaf(name, ustrlen(name));
- CHKiRet(jsonPathFindParent(pM, 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;
}
@@ -3900,29 +3900,45 @@ 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[1] == '\0') {
- if(pM->json == NULL)
- pM->json = json;
+ 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
- CHKiRet(jsonMerge(pM->json, json));
+ CHKiRet(jsonMerge(*pjroot, json));
} else {
- if(pM->json == NULL) {
+ if(*pjroot == NULL) {
/* now we need a root obj */
- pM->json = json_object_new_object();
+ *pjroot = json_object_new_object();
}
leaf = jsonPathGetLeaf(name, ustrlen(name));
- CHKiRet(jsonPathFindParent(pM, name, leaf, &parent, 1));
+ CHKiRet(jsonPathFindParent(*pjroot, name, leaf, &parent, 1));
+ if (json_object_get_type(parent) != json_type_object) {
+ DBGPRINTF("msgAddJSON: not a container in json path,"
+ "name is '%s'\n", name);
+ json_object_put(json);
+ ABORT_FINALIZE(RS_RET_INVLD_SETOP);
+ }
leafnode = json_object_object_get(parent, (char*)leaf);
if(leafnode == NULL) {
json_object_object_add(parent, (char*)leaf, json);
} else {
if(json_object_get_type(json) == json_type_object) {
- CHKiRet(jsonMerge(pM->json, json));
+ CHKiRet(jsonMerge(*pjroot, json));
} else {
//dbgprintf("AAAA: leafnode already exists, type is %d, update with %d\n", (int)json_object_get_type(leafnode), (int)json_object_get_type(json));
/* TODO: improve the code below, however, the current
@@ -3948,33 +3964,52 @@ msgAddJSON(msg_t *pM, uchar *name, struct json_object *json)
}
finalize_it:
+ if(name[0] == '/')
+ pthread_rwlock_unlock(&glblVars_rwlock);
MsgUnlock(pM);
RETiRet;
}
+
rsRetVal
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[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");
- json_object_put(pM->json);
- pM->json = NULL;
+ json_object_put(*jroot);
+ *jroot = NULL;
} else {
- if(pM->json == NULL) {
+ if(*jroot == NULL) {
/* now we need a root obj */
- pM->json = json_object_new_object();
+ *jroot = json_object_new_object();
}
leaf = jsonPathGetLeaf(name, ustrlen(name));
- CHKiRet(jsonPathFindParent(pM, name, leaf, &parent, 1));
+ CHKiRet(jsonPathFindParent(*jroot, name, leaf, &parent, 1));
leafnode = json_object_object_get(parent, (char*)leaf);
DBGPRINTF("AAAA: unset found JSON value path '%s', " "leaf '%s', leafnode %p\n", name, leaf, leafnode);
if(leafnode == NULL) {
@@ -3989,6 +4024,8 @@ 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;
}
@@ -4010,7 +4047,11 @@ jsonDeepCopy(struct json_object *src)
dst = json_object_new_double(json_object_get_double(src));
break;
case json_type_int:
+#ifdef HAVE_JSON_OBJECT_NEW_INT64
+ dst = json_object_new_int64(json_object_get_int64(src));
+#else /* HAVE_JSON_OBJECT_NEW_INT64 */
dst = json_object_new_int(json_object_get_int(src));
+#endif /* HAVE_JSON_OBJECT_NEW_INT64 */
break;
case json_type_string:
dst = json_object_new_string(json_object_get_string(src));
@@ -4053,7 +4094,11 @@ msgSetJSONFromVar(msg_t *pMsg, uchar *varname, struct var *v)
free(cstr);
break;
case 'N':/* number (integer) */
+#ifdef HAVE_JSON_OBJECT_NEW_INT64
+ json = json_object_new_int64(v->d.n);
+#else /* HAVE_JSON_OBJECT_NEW_INT64 */
json = json_object_new_int((int) v->d.n);
+#endif /* HAVE_JSON_OBJECT_NEW_INT64 */
break;
case 'J':/* native JSON */
json = jsonDeepCopy(v->d.json);
@@ -4062,7 +4107,8 @@ msgSetJSONFromVar(msg_t *pMsg, uchar *varname, struct var *v)
v->datatype);
ABORT_FINALIZE(RS_RET_ERR);
}
- msgAddJSON(pMsg, varname+1, json);
+
+ msgAddJSON(pMsg, varname, json);
finalize_it:
RETiRet;
}
@@ -4088,6 +4134,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; }
@@ -4096,6 +4185,8 @@ rsRetVal msgQueryInterface(void) { return RS_RET_NOT_IMPLEMENTED; }
* rgerhards, 2008-01-04
*/
BEGINObjClassInit(msg, 1, OBJ_IS_CORE_MODULE)
+ pthread_rwlock_init(&glblVars_rwlock, NULL);
+
/* request objects we use */
CHKiRet(objUse(datetime, CORE_COMPONENT));
CHKiRet(objUse(glbl, CORE_COMPONENT));