summaryrefslogtreecommitdiffstats
path: root/runtime/msg.c
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/msg.c')
-rw-r--r--runtime/msg.c331
1 files changed, 235 insertions, 96 deletions
diff --git a/runtime/msg.c b/runtime/msg.c
index 03906070..991da436 100644
--- a/runtime/msg.c
+++ b/runtime/msg.c
@@ -66,6 +66,12 @@
#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
+ */
+static pthread_rwlock_t glblVars_rwlock;
+struct json_object *global_var_root = NULL;
+
/* static data */
DEFobjStaticHelpers
DEFobjCurrIf(datetime)
@@ -317,9 +323,10 @@ 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);
+static rsRetVal msgAddJSONObj(msg_t *pM, uchar *name, struct json_object *json, struct json_object **pjroot);
/* the locking and unlocking implementations: */
@@ -377,13 +384,6 @@ MsgSetRulesetByName(msg_t *pMsg, cstr_t *rulesetName)
rulesetGetRuleset(runConf, &(pMsg->pRuleset), rsCStrGetSzStrNoNULL(rulesetName));
}
-
-static inline int getProtocolVersion(msg_t *pM)
-{
- return(pM->iProtocolVersion);
-}
-
-
/* do a DNS reverse resolution, if not already done, reflect status
* rgerhards, 2009-11-16
*/
@@ -536,11 +536,16 @@ propNameStrToID(uchar *pName, propid_t *pPropID)
*pPropID = PROP_CEE_ALL_JSON;
} else if(!strncmp((char*) pName, "$!", 2)) {
*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")) {
*pPropID = PROP_SYS_UPTIME;
} else {
+ DBGPRINTF("PROP_INVALID for name '%s'\n", pName);
*pPropID = PROP_INVALID;
iRet = RS_RET_VAR_NOT_FOUND;
}
@@ -634,6 +639,10 @@ 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_GLOBAL_VAR:
+ return UCHAR_CONSTANT("*GLOBAL_VARIABLE*");
case PROP_CEE_ALL_JSON:
return UCHAR_CONSTANT("$!all-json");
case PROP_SYS_BOM:
@@ -699,7 +708,7 @@ static inline rsRetVal msgBaseConstruct(msg_t **ppThis)
pM->pszTIMESTAMP3339 = NULL;
pM->pszTIMESTAMP_MySQL = NULL;
pM->pszTIMESTAMP_PgSQL = NULL;
- pM->pCSStrucData = NULL;
+ pM->pszStrucData = NULL;
pM->pCSAPPNAME = NULL;
pM->pCSPROCID = NULL;
pM->pCSMSGID = NULL;
@@ -708,6 +717,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;
@@ -841,10 +852,9 @@ CODESTARTobjDestruct(msg)
free(pThis->pszRcvdAt_PgSQL);
free(pThis->pszTIMESTAMP_MySQL);
free(pThis->pszTIMESTAMP_PgSQL);
+ free(pThis->pszStrucData);
if(pThis->iLenPROGNAME >= CONF_PROGNAME_BUFSIZE)
free(pThis->PROGNAME.ptr);
- if(pThis->pCSStrucData != NULL)
- rsCStrDestruct(&pThis->pCSStrucData);
if(pThis->pCSAPPNAME != NULL)
rsCStrDestruct(&pThis->pCSAPPNAME);
if(pThis->pCSPROCID != NULL)
@@ -853,6 +863,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
@@ -994,14 +1006,21 @@ msg_t* MsgDup(msg_t* pOld)
tmpCOPYSZ(HOSTNAME);
}
}
+ if(pOld->pszStrucData == NULL) {
+ pNew->pszStrucData = NULL;
+ } else {
+ pNew->pszStrucData = (uchar*)strdup((char*)pOld->pszStrucData);
+ pNew->lenStrucData = pOld->lenStrucData;
+ }
- tmpCOPYCSTR(StrucData);
tmpCOPYCSTR(APPNAME);
tmpCOPYCSTR(PROCID);
tmpCOPYCSTR(MSGID);
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.
@@ -1056,12 +1075,17 @@ static rsRetVal MsgSerialize(msg_t *pThis, strm_t *pStrm)
CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("pszRcvFrom"), PROPTYPE_PSZ, (void*) psz));
psz = getRcvFromIP(pThis);
CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("pszRcvFromIP"), PROPTYPE_PSZ, (void*) psz));
+ psz = pThis->pszStrucData;
+ CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("pszRcvStrucData"), PROPTYPE_PSZ, (void*) psz));
if(pThis->json != NULL) {
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, pCSStrucData, CSTR);
objSerializePTR(pStrm, pCSAPPNAME, CSTR);
objSerializePTR(pStrm, pCSPROCID, CSTR);
objSerializePTR(pStrm, pCSMSGID, CSTR);
@@ -1202,7 +1226,15 @@ MsgDeserialize(msg_t *pMsg, strm_t *pStrm)
reinitVar(pVar);
CHKiRet(objDeserializeProperty(pVar, pStrm));
}
- if(isProp("pCSStrucData")) {
+ 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);
CHKiRet(objDeserializeProperty(pVar, pStrm));
@@ -1292,7 +1324,7 @@ static rsRetVal aquirePROCIDFromTAG(msg_t *pM)
if(pM->pCSPROCID != NULL)
return RS_RET_OK; /* we are already done ;) */
- if(getProtocolVersion(pM) != 0)
+ if(msgGetProtocolVersion(pM) != 0)
return RS_RET_OK; /* we can only emulate if we have legacy format */
pszTag = (uchar*) ((pM->iLenTAG < CONF_TAG_BUFSIZE) ? pM->TAG.szBuf : pM->TAG.pszTAG);
@@ -1975,7 +2007,7 @@ static inline void tryEmulateTAG(msg_t *pM, sbool bLockMutex)
return; /* done, no need to emulate */
}
- if(getProtocolVersion(pM) == 1) {
+ if(msgGetProtocolVersion(pM) == 1) {
if(!strcmp(getPROCID(pM, MUTEX_ALREADY_LOCKED), "-")) {
/* no process ID, use APP-NAME only */
MsgSetTAG(pM, (uchar*) getAPPNAME(pM, MUTEX_ALREADY_LOCKED), getAPPNAMELen(pM, MUTEX_ALREADY_LOCKED));
@@ -2075,42 +2107,27 @@ rsRetVal MsgSetStructuredData(msg_t *pMsg, char* pszStrucData)
{
DEFiRet;
ISOBJ_TYPE_assert(pMsg, msg);
- if(pMsg->pCSStrucData == NULL) {
- /* we need to obtain the object first */
- CHKiRet(rsCStrConstruct(&pMsg->pCSStrucData));
- }
- /* if we reach this point, we have the object */
- iRet = rsCStrSetSzStr(pMsg->pCSStrucData, (uchar*) pszStrucData);
-
+ free(pMsg->pszStrucData);
+ CHKmalloc(pMsg->pszStrucData = (uchar*)strdup(pszStrucData));
+ pMsg->lenStrucData = strlen(pszStrucData);
finalize_it:
RETiRet;
}
-/* get the length of the "STRUCTURED-DATA" sz string
- * rgerhards, 2005-11-24
- */
-#if 0 /* This method is currently not called, be we like to preserve it */
-static int getStructuredDataLen(msg_t *pM)
-{
- return (pM->pCSStrucData == NULL) ? 1 : rsCStrLen(pM->pCSStrucData);
-}
-#endif
-
-/* get the "STRUCTURED-DATA" as sz string
- * rgerhards, 2005-11-24
- */
-static inline char *getStructuredData(msg_t *pM)
+/* get the "STRUCTURED-DATA" as sz string, including length */
+void
+MsgGetStructuredData(msg_t *pM, uchar **pBuf, rs_size_t *len)
{
- uchar *pszRet;
-
MsgLock(pM);
- if(pM->pCSStrucData == NULL)
- pszRet = UCHAR_CONSTANT("-");
- else
- pszRet = rsCStrGetSzStrNoNULL(pM->pCSStrucData);
+ if(pM->pszStrucData == NULL) {
+ *pBuf = UCHAR_CONSTANT("-"),
+ *len = 1;
+ } else {
+ *pBuf = pM->pszStrucData,
+ *len = pM->lenStrucData;
+ }
MsgUnlock(pM);
- return (char*) pszRet;
}
/* get the "programname" as sz string
@@ -2145,7 +2162,7 @@ static void tryEmulateAPPNAME(msg_t *pM)
if(pM->pCSAPPNAME != NULL)
return; /* we are already done */
- if(getProtocolVersion(pM) == 0) {
+ if(msgGetProtocolVersion(pM) == 0) {
/* only then it makes sense to emulate */
MsgSetAPPNAME(pM, (char*)getProgramName(pM, MUTEX_ALREADY_LOCKED));
}
@@ -2215,6 +2232,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
@@ -2510,9 +2536,9 @@ static uchar *getNOW(eNOWType eNow, struct syslogTime *t)
#undef tmpBUFSIZE /* clean up */
-/* Get a CEE-Property as string value*/
-rsRetVal
-getCEEPropVal(msg_t *pM, es_str_t *propName, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed)
+/* Get a JSON-Property as string value (used for various types of JSON-based vars) */
+static rsRetVal
+getJSONPropVal(struct json_object *jroot, es_str_t *propName, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed)
{
uchar *name = NULL;
uchar *leaf;
@@ -2524,14 +2550,14 @@ getCEEPropVal(msg_t *pM, es_str_t *propName, uchar **pRes, rs_size_t *buflen, un
free(*pRes);
*pRes = NULL;
// TODO: mutex?
- if(pM->json == NULL) goto finalize_it;
+ if(jroot == NULL) goto finalize_it;
if(!es_strbufcmp(propName, (uchar*)"!", 1)) {
- field = pM->json;
+ field = jroot;
} else {
name = (uchar*)es_str2cstr(propName, NULL);
leaf = jsonPathGetLeaf(name, ustrlen(name));
- CHKiRet(jsonPathFindParent(pM, name, leaf, &parent, 1));
+ CHKiRet(jsonPathFindParent(jroot, name, leaf, &parent, 1));
field = json_object_object_get(parent, (char*)leaf);
}
if(field != NULL) {
@@ -2550,11 +2576,32 @@ finalize_it:
RETiRet;
}
+rsRetVal
+getCEEPropVal(msg_t *pM, es_str_t *propName, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed)
+{
+ return getJSONPropVal(pM->json, propName, pRes, buflen, pbMustBeFreed);
+}
-/* Get a CEE-Property as native json object
- */
rsRetVal
-msgGetCEEPropJSON(msg_t *pM, es_str_t *propName, struct json_object **pjson)
+getLocalVarPropVal(msg_t *pM, es_str_t *propName, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed)
+{
+ return getJSONPropVal(pM->localvars, propName, pRes, buflen, pbMustBeFreed);
+}
+
+rsRetVal
+getGlobalVarPropVal( es_str_t *propName, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed)
+{
+ DEFiRet;
+ pthread_rwlock_rdlock(&glblVars_rwlock);
+ iRet = getJSONPropVal(global_var_root, propName, pRes, buflen, pbMustBeFreed);
+ pthread_rwlock_unlock(&glblVars_rwlock);
+ RETiRet;
+}
+
+
+/* Get a JSON-based-variable as native json object */
+rsRetVal
+msgGetJSONPropJSON(struct json_object *jroot, es_str_t *propName, struct json_object **pjson)
{
uchar *name = NULL;
uchar *leaf;
@@ -2562,17 +2609,17 @@ msgGetCEEPropJSON(msg_t *pM, es_str_t *propName, struct json_object **pjson)
DEFiRet;
// TODO: mutex?
- if(pM->json == NULL) {
+ if(jroot == NULL) {
ABORT_FINALIZE(RS_RET_NOT_FOUND);
}
if(!es_strbufcmp(propName, (uchar*)"!", 1)) {
- *pjson = pM->json;
+ *pjson = jroot;
FINALIZE;
}
name = (uchar*)es_str2cstr(propName, NULL);
leaf = jsonPathGetLeaf(name, ustrlen(name));
- CHKiRet(jsonPathFindParent(pM, name, leaf, &parent, 1));
+ CHKiRet(jsonPathFindParent(jroot, name, leaf, &parent, 1));
*pjson = json_object_object_get(parent, (char*)leaf);
if(*pjson == NULL) {
ABORT_FINALIZE(RS_RET_NOT_FOUND);
@@ -2583,6 +2630,27 @@ finalize_it:
RETiRet;
}
+rsRetVal
+msgGetCEEPropJSON(msg_t *pM, es_str_t *propName, struct json_object **pjson)
+{
+ return msgGetJSONPropJSON(pM->json, propName, pjson);
+}
+
+rsRetVal
+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)
+{
+ DEFiRet;
+ pthread_rwlock_rdlock(&glblVars_rwlock);
+ iRet = msgGetJSONPropJSON(global_var_root, propName, pjson);
+ pthread_rwlock_unlock(&glblVars_rwlock);
+ RETiRet;
+}
/* Encode a JSON value and add it to provided string. Note that
* the string object may be NULL. In this case, it is created
@@ -2880,7 +2948,7 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
pRes = (uchar*)getProtocolVersionString(pMsg);
break;
case PROP_STRUCTURED_DATA:
- pRes = (uchar*)getStructuredData(pMsg);
+ MsgGetStructuredData(pMsg, &pRes, &bufLen);
break;
case PROP_APP_NAME:
pRes = (uchar*)getAPPNAME(pMsg, LOCK_MUTEX);
@@ -2981,6 +3049,12 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
case PROP_CEE:
getCEEPropVal(pMsg, propName, &pRes, &bufLen, pbMustBeFreed);
break;
+ 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);
@@ -3648,15 +3722,15 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
}
-/* The function returns a cee variable suitable for use with RainerScript.
+/* The function returns a json 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)
+static es_str_t*
+msgGetJSONVarNew(msg_t *pMsg, struct json_object *jroot, char *name)
{
uchar *leaf;
char *val;
@@ -3665,12 +3739,12 @@ msgGetCEEVarNew(msg_t *pMsg, char *name)
ISOBJ_TYPE_assert(pMsg, msg);
- if(pMsg->json == NULL) {
+ if(jroot == NULL) {
estr = es_newStr(1);
goto done;
}
leaf = jsonPathGetLeaf((uchar*)name, strlen(name));
- if(jsonPathFindParent(pMsg, (uchar*)name, leaf, &parent, 1) != RS_RET_OK) {
+ if(jsonPathFindParent(jroot, (uchar*)name, leaf, &parent, 1) != RS_RET_OK) {
estr = es_newStr(1);
goto done;
}
@@ -3681,6 +3755,17 @@ done:
return estr;
}
+es_str_t*
+msgGetCEEVarNew(msg_t *pMsg, char *name)
+{
+ return msgGetJSONVarNew(pMsg, pMsg->json, name);
+}
+
+es_str_t*
+msgGetLocalVarNew(msg_t *pMsg, char *name)
+{
+ return msgGetJSONVarNew(pMsg, pMsg->localvars, name);
+}
/* Return an es_str_t for given message property.
*/
@@ -3692,13 +3777,16 @@ msgGetMsgVarNew(msg_t *pThis, uchar *name)
propid_t propid;
unsigned short bMustBeFreed = 0;
es_str_t *estr;
+ es_str_t *propName;
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);
+ propName = es_newStrFromCStr((char*)name, ustrlen(name)); // TODO: optimize!
+ pszProp = (uchar*) MsgGetProp(pThis, NULL, propid, propName, &propLen, &bMustBeFreed, NULL);
+ es_deleteStr(propName);
estr = es_newStrFromCStr((char*)pszProp, propLen);
if(bMustBeFreed)
@@ -3758,7 +3846,7 @@ rsRetVal MsgSetProperty(msg_t *pThis, var_t *pProp)
prop.Destruct(&propRcvFrom);
} else if(isProp("pszHOSTNAME")) {
MsgSetHOSTNAME(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr), rsCStrLen(pProp->val.pStr));
- } else if(isProp("pCSStrucData")) {
+ } else if(isProp("pszStrucData")) {
MsgSetStructuredData(pThis, (char*) rsCStrGetSzStrNoNULL(pProp->val.pStr));
} else if(isProp("pCSAPPNAME")) {
MsgSetAPPNAME(pThis, (char*) rsCStrGetSzStrNoNULL(pProp->val.pStr));
@@ -3809,16 +3897,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];
@@ -3827,9 +3921,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';
@@ -3853,12 +3947,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;
}
@@ -3885,7 +3981,7 @@ 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, es_str_t *propName, struct json_object **jsonres)
{
uchar *name = NULL;
uchar *leaf;
@@ -3893,17 +3989,17 @@ jsonFind(msg_t *pM, es_str_t *propName, struct json_object **jsonres)
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;
+ field = jroot;
} else {
name = (uchar*)es_str2cstr(propName, NULL);
leaf = jsonPathGetLeaf(name, ustrlen(name));
- CHKiRet(jsonPathFindParent(pM, name, leaf, &parent, 0));
+ CHKiRet(jsonPathFindParent(jroot, name, leaf, &parent, 0));
field = json_object_object_get(parent, (char*)leaf);
}
*jsonres = field;
@@ -3913,8 +4009,8 @@ finalize_it:
RETiRet;
}
-rsRetVal
-msgAddJSON(msg_t *pM, uchar *name, struct json_object *json)
+static rsRetVal
+msgAddJSONObj(msg_t *pM, uchar *name, struct json_object *json, struct json_object **pjroot)
{
/* TODO: error checks! This is a quick&dirty PoC! */
struct json_object *parent, *leafnode;
@@ -3922,24 +4018,24 @@ msgAddJSON(msg_t *pM, uchar *name, struct json_object *json)
DEFiRet;
MsgLock(pM);
- if(name[0] == '!' && name[1] == '\0') {
- if(pM->json == NULL)
- pM->json = json;
+ if((name[0] == '!' || name[0] == '.' || name[0] == '/') && name[1] == '\0') {
+ 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));
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
@@ -3970,7 +4066,12 @@ finalize_it:
}
rsRetVal
-msgDelJSON(msg_t *pM, uchar *name)
+msgAddJSON(msg_t *pM, uchar *name, struct json_object *json) {
+ return msgAddJSONObj(pM, name, json, &pM->json);
+}
+
+rsRetVal
+msgDelJSONVar(msg_t *pM, struct json_object **jroot, uchar *name)
{
struct json_object *parent, *leafnode;
uchar *leaf;
@@ -3978,20 +4079,20 @@ msgDelJSON(msg_t *pM, uchar *name)
dbgprintf("AAAA: unset variable '%s'\n", name);
MsgLock(pM);
- if(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.
*/
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) {
@@ -4010,6 +4111,12 @@ finalize_it:
RETiRet;
}
+rsRetVal
+msgDelJSON(msg_t *pM, uchar *name)
+{
+ return msgDelJSONVar(pM, &pM->json, name);
+}
+
static struct json_object *
jsonDeepCopy(struct json_object *src)
{
@@ -4079,11 +4186,41 @@ msgSetJSONFromVar(msg_t *pMsg, uchar *varname, struct var *v)
v->datatype);
ABORT_FINALIZE(RS_RET_ERR);
}
- msgAddJSON(pMsg, varname+1, json);
+ /* we always know strlen(varname) > 2 */
+ if(varname[1] == '!')
+ msgAddJSONObj(pMsg, varname+1, json, &pMsg->json);
+ else if(varname[1] == '.')
+ msgAddJSONObj(pMsg, varname+1, json, &pMsg->localvars);
+ else { /* global - '/' */
+ pthread_rwlock_wrlock(&glblVars_rwlock);
+ msgAddJSONObj(pMsg, varname+1, json, &global_var_root);
+ pthread_rwlock_unlock(&glblVars_rwlock);
+ }
finalize_it:
RETiRet;
}
+rsRetVal
+MsgAddToStructuredData(msg_t *pMsg, uchar *toadd, rs_size_t len)
+{
+ uchar *newptr;
+ rs_size_t newlen;
+ DEFiRet;
+ newlen = (pMsg->pszStrucData[0] == '-') ? len : pMsg->lenStrucData + len;
+ CHKmalloc(newptr = (uchar*) realloc(pMsg->pszStrucData, newlen+1));
+ pMsg->pszStrucData = newptr;
+ if(pMsg->pszStrucData[0] == '-') { /* empty? */
+ memcpy(pMsg->pszStrucData, toadd, len);
+ } else {
+ memcpy(pMsg->pszStrucData+pMsg->lenStrucData, toadd, len);
+ }
+ pMsg->pszStrucData[newlen] = '\0';
+ pMsg->lenStrucData = newlen;
+finalize_it:
+ RETiRet;
+}
+
+
/* dummy */
rsRetVal msgQueryInterface(void) { return RS_RET_NOT_IMPLEMENTED; }
@@ -4092,6 +4229,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));