summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/cfsysline.c51
-rw-r--r--runtime/cfsysline.h20
-rw-r--r--runtime/conf.c145
-rw-r--r--runtime/conf.h10
-rw-r--r--runtime/glbl.c18
-rw-r--r--runtime/glbl.h2
-rw-r--r--runtime/module-template.h54
-rw-r--r--runtime/modules.c7
-rw-r--r--runtime/modules.h6
-rw-r--r--runtime/parser.c12
-rw-r--r--runtime/rsyslog.h45
-rw-r--r--runtime/ruleset.c4
12 files changed, 315 insertions, 59 deletions
diff --git a/runtime/cfsysline.c b/runtime/cfsysline.c
index 5df8e64c..1743b818 100644
--- a/runtime/cfsysline.c
+++ b/runtime/cfsysline.c
@@ -39,6 +39,7 @@
#include "cfsysline.h"
#include "obj.h"
+#include "conf.h"
#include "errmsg.h"
#include "srUtils.h"
@@ -655,11 +656,13 @@ static int cslchKeyCompare(void *pKey1, void *pKey2)
/* set data members for this object
*/
-rsRetVal cslchSetEntry(cslCmdHdlr_t *pThis, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData)
+rsRetVal cslchSetEntry(cslCmdHdlr_t *pThis, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(),
+ void *pData, ecslConfObjType eConfObjType)
{
assert(pThis != NULL);
assert(eType != eCmdHdlrInvalid);
+ pThis->eConfObjType = eConfObjType;
pThis->eType = eType;
pThis->cslCmdHdlr = pHdlr;
pThis->pData = pData;
@@ -776,7 +779,8 @@ finalize_it:
/* add a handler entry to a known command
*/
-static rsRetVal cslcAddHdlr(cslCmd_t *pThis, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData, void *pOwnerCookie)
+static rsRetVal cslcAddHdlr(cslCmd_t *pThis, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData,
+ void *pOwnerCookie, ecslConfObjType eConfObjType)
{
DEFiRet;
cslCmdHdlr_t *pCmdHdlr = NULL;
@@ -784,7 +788,7 @@ static rsRetVal cslcAddHdlr(cslCmd_t *pThis, ecslCmdHdrlType eType, rsRetVal (*p
assert(pThis != NULL);
CHKiRet(cslchConstruct(&pCmdHdlr));
- CHKiRet(cslchSetEntry(pCmdHdlr, eType, pHdlr, pData));
+ CHKiRet(cslchSetEntry(pCmdHdlr, eType, pHdlr, pData, eConfObjType));
CHKiRet(llAppend(&pThis->llCmdHdlrs, pOwnerCookie, pCmdHdlr));
finalize_it:
@@ -804,7 +808,7 @@ finalize_it:
* free pCmdName if he allocated it dynamically! -- rgerhards, 2007-08-09
*/
rsRetVal regCfSysLineHdlr(uchar *pCmdName, int bChainingPermitted, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData,
- void *pOwnerCookie)
+ void *pOwnerCookie, ecslConfObjType eConfObjType)
{
DEFiRet;
cslCmd_t *pThis;
@@ -814,7 +818,7 @@ rsRetVal regCfSysLineHdlr(uchar *pCmdName, int bChainingPermitted, ecslCmdHdrlTy
if(iRet == RS_RET_NOT_FOUND) {
/* new command */
CHKiRet(cslcConstruct(&pThis, bChainingPermitted));
- CHKiRet_Hdlr(cslcAddHdlr(pThis, eType, pHdlr, pData, pOwnerCookie)) {
+ CHKiRet_Hdlr(cslcAddHdlr(pThis, eType, pHdlr, pData, pOwnerCookie, eConfObjType)) {
cslcDestruct(pThis);
FINALIZE;
}
@@ -834,7 +838,7 @@ rsRetVal regCfSysLineHdlr(uchar *pCmdName, int bChainingPermitted, ecslCmdHdrlTy
if(pThis->bChainingPermitted == 0 || bChainingPermitted == 0) {
ABORT_FINALIZE(RS_RET_CHAIN_NOT_PERMITTED);
}
- CHKiRet_Hdlr(cslcAddHdlr(pThis, eType, pHdlr, pData, pOwnerCookie)) {
+ CHKiRet_Hdlr(cslcAddHdlr(pThis, eType, pHdlr, pData, pOwnerCookie, eConfObjType)) {
cslcDestruct(pThis);
FINALIZE;
}
@@ -909,6 +913,7 @@ rsRetVal processCfSysLineCommand(uchar *pCmdName, uchar **p)
uchar *pHdlrP; /* the handler's private p (else we could only call one handler) */
int bWasOnceOK; /* was the result of an handler at least once RS_RET_OK? */
uchar *pOKp = NULL; /* returned conf line pointer when it was OK */
+ int bHadScopingErr = 0; /* set if a scoping error occured */
iRet = llFind(&llCmdList, (void *) pCmdName, (void*) &pCmd);
@@ -922,17 +927,25 @@ rsRetVal processCfSysLineCommand(uchar *pCmdName, uchar **p)
llCookieCmdHdlr = NULL;
bWasOnceOK = 0;
while((iRetLL = llGetNextElt(&pCmd->llCmdHdlrs, &llCookieCmdHdlr, (void*)&pCmdHdlr)) == RS_RET_OK) {
- /* for the time being, we ignore errors during handlers. The
- * reason is that handlers are independent. An error in one
- * handler does not necessarily mean that another one will
- * fail, too. Later, we might add a config variable to control
- * this behaviour (but I am not sure if that is rally
- * necessary). -- rgerhards, 2007-07-31
- */
- pHdlrP = *p;
- if((iRet = cslchCallHdlr(pCmdHdlr, &pHdlrP)) == RS_RET_OK) {
- bWasOnceOK = 1;
- pOKp = pHdlrP;
+ /* check if handler is valid in current scope */
+ if(pCmdHdlr->eConfObjType == eConfObjAlways ||
+ (bConfStrictScoping == 0 && currConfObj == eConfObjGlobal) ||
+ pCmdHdlr->eConfObjType == currConfObj) {
+ /* for the time being, we ignore errors during handlers. The
+ * reason is that handlers are independent. An error in one
+ * handler does not necessarily mean that another one will
+ * fail, too. Later, we might add a config variable to control
+ * this behaviour (but I am not sure if that is really
+ * necessary). -- rgerhards, 2007-07-31
+ */
+ pHdlrP = *p;
+ if((iRet = cslchCallHdlr(pCmdHdlr, &pHdlrP)) == RS_RET_OK) {
+ bWasOnceOK = 1;
+ pOKp = pHdlrP;
+ }
+ } else {
+ errmsg.LogError(0, RS_RET_CONF_INVLD_SCOPE, "config command invalid for current scope");
+ bHadScopingErr = 1;
}
}
@@ -944,6 +957,10 @@ rsRetVal processCfSysLineCommand(uchar *pCmdName, uchar **p)
if(iRetLL != RS_RET_END_OF_LINKEDLIST)
iRet = iRetLL;
+ if(bHadScopingErr) {
+ iRet = RS_RET_CONF_INVLD_SCOPE;
+ }
+
finalize_it:
RETiRet;
}
diff --git a/runtime/cfsysline.h b/runtime/cfsysline.h
index 07ab5fcd..a4502672 100644
--- a/runtime/cfsysline.h
+++ b/runtime/cfsysline.h
@@ -26,28 +26,12 @@
#include "linkedlist.h"
-/* types of configuration handlers
- */
-typedef enum cslCmdHdlrType {
- eCmdHdlrInvalid = 0, /* invalid handler type - indicates a coding error */
- eCmdHdlrCustomHandler, /* custom handler, just call handler function */
- eCmdHdlrUID,
- eCmdHdlrGID,
- eCmdHdlrBinary,
- eCmdHdlrFileCreateMode,
- eCmdHdlrInt,
- eCmdHdlrSize,
- eCmdHdlrGetChar,
- eCmdHdlrFacility,
- eCmdHdlrSeverity,
- eCmdHdlrGetWord
-} ecslCmdHdrlType;
-
/* this is a single entry for a parse routine. It describes exactly
* one entry point/handler.
* The short name is cslch (Configfile SysLine CommandHandler)
*/
struct cslCmdHdlr_s { /* config file sysline parse entry */
+ ecslConfObjType eConfObjType; /* which config object is this for? */
ecslCmdHdrlType eType; /* which type of handler is this? */
rsRetVal (*cslCmdHdlr)(); /* function pointer to use with handler (params depending on eType) */
void *pData; /* user-supplied data pointer */
@@ -66,7 +50,7 @@ struct cslCmd_s { /* config file sysline parse entry */
typedef struct cslCmd_s cslCmd_t;
/* prototypes */
-rsRetVal regCfSysLineHdlr(uchar *pCmdName, int bChainingPermitted, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData, void *pOwnerCookie);
+rsRetVal regCfSysLineHdlr(uchar *pCmdName, int bChainingPermitted, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData, void *pOwnerCookie, ecslConfObjType eConfObjType);
rsRetVal unregCfSysLineHdlrs(void);
rsRetVal unregCfSysLineHdlrs4Owner(void *pOwnerCookie);
rsRetVal processCfSysLineCommand(uchar *pCmd, uchar **p);
diff --git a/runtime/conf.c b/runtime/conf.c
index d41f2950..1f0badcb 100644
--- a/runtime/conf.c
+++ b/runtime/conf.c
@@ -52,7 +52,6 @@
#endif
#include "rsyslog.h"
-#include "../tools/syslogd.h" /* TODO: this must be removed! */
#include "dirty.h"
#include "parse.h"
#include "action.h"
@@ -93,6 +92,10 @@ DEFobjCurrIf(net)
DEFobjCurrIf(rule)
DEFobjCurrIf(ruleset)
+ecslConfObjType currConfObj = eConfObjGlobal; /* to support scoping - which config object is currently active? */
+int bConfStrictScoping = 0; /* force strict scoping during config processing? */
+
+
static int iNbrActions = 0; /* number of currently defined actions */
/* The following module-global variables are used for building
@@ -1097,6 +1100,11 @@ static rsRetVal cflineDoAction(uchar **p, action_t **ppAction)
iRet = pMod->mod.om.parseSelectorAct(p, &pModData, &pOMSR);
dbgprintf("tried selector action for %s: %d\n", module.GetName(pMod), iRet);
if(iRet == RS_RET_OK || iRet == RS_RET_SUSPENDED) {
+ /* advance our config parser state: we now only accept an $End as valid,
+ * no more action statments.
+ */
+ if(currConfObj == eConfObjAction)
+ currConfObj = eConfObjActionWaitEnd;
if((iRet = addAction(&pAction, pMod, pModData, pOMSR, (iRet == RS_RET_SUSPENDED)? 1 : 0)) == RS_RET_OK) {
/* now check if the module is compatible with select features */
if(pMod->isCompatibleWithFeature(sFEATURERepeatedMsgReduction) == RS_RET_OK)
@@ -1246,6 +1254,136 @@ finalize_it:
ENDobjQueryInterface(conf)
+/* switch to a new action scope. This means that we switch the current
+ * mode to action, but it also means we need to clear all scope variables,
+ * so that we have a new environment.
+ * rgerhards, 2010-07-23
+ */
+static inline rsRetVal
+setActionScope(void)
+{
+ DEFiRet;
+ modInfo_t *pMod;
+
+ currConfObj = eConfObjAction;
+ DBGPRINTF("entering action scope\n");
+ CHKiRet(actionNewScope());
+
+ /* now tell each action to start the scope */
+ pMod = NULL;
+ while((pMod = module.GetNxtType(pMod, eMOD_OUT)) != NULL) {
+ DBGPRINTF("beginning scope on module %s\n", pMod->pszName);
+ pMod->mod.om.newScope();
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* switch back from action scope.
+ * rgerhards, 2010-07-27
+ */
+static inline rsRetVal
+unsetActionScope(void)
+{
+ DEFiRet;
+ modInfo_t *pMod;
+
+ currConfObj = eConfObjAction;
+ DBGPRINTF("exiting action scope\n");
+ CHKiRet(actionRestoreScope());
+
+ /* now tell each action to restore the scope */
+ pMod = NULL;
+ while((pMod = module.GetNxtType(pMod, eMOD_OUT)) != NULL) {
+ DBGPRINTF("exiting scope on module %s\n", pMod->pszName);
+ pMod->mod.om.restoreScope();
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* This method is called by our own handlers to begin a new config
+ * object ($Begin statement). This also implies a new scope.
+ * rgerhards, 2010-07-23
+ */
+static rsRetVal
+beginConfObj(void __attribute__((unused)) *pVal, uchar *pszName)
+{
+ DEFiRet;
+
+ if(currConfObj != eConfObjGlobal) {
+ errmsg.LogError(0, RS_RET_CONF_NOT_GLBL, "not in global scope - can not nest $Begin");
+ ABORT_FINALIZE(RS_RET_CONF_NOT_GLBL);
+ }
+
+ if(!strcasecmp((char*)pszName, "action")) {
+ setActionScope();
+ } else {
+ errmsg.LogError(0, RS_RET_INVLD_CONF_OBJ, "invalid config object \"%s\" in $Begin", pszName);
+ ABORT_FINALIZE(RS_RET_INVLD_CONF_OBJ);
+ }
+
+finalize_it:
+ free(pszName); /* no longer needed */
+ RETiRet;
+}
+
+
+/* This method is called to end a config scope and switch
+ * back to global scope.
+ * rgerhards, 2010-07-23
+ */
+static rsRetVal
+endConfObj(void __attribute__((unused)) *pVal, uchar *pszName)
+{
+ DEFiRet;
+
+ if(currConfObj == eConfObjGlobal) {
+ errmsg.LogError(0, RS_RET_CONF_NOT_GLBL, "already in global scope - dangling $End");
+ ABORT_FINALIZE(RS_RET_CONF_IN_GLBL);
+ }
+
+ if(!strcasecmp((char*)pszName, "action")) {
+ if(currConfObj == eConfObjAction) {
+ errmsg.LogError(0, RS_RET_CONF_END_NO_ACT, "$End action but not action specified");
+ /* this is a warning, we continue processing in that case (unscope) */
+ } else if(currConfObj != eConfObjActionWaitEnd) {
+ errmsg.LogError(0, RS_RET_CONF_INVLD_END, "$End not for active config object - "
+ "nesting error?");
+ ABORT_FINALIZE(RS_RET_CONF_INVLD_END);
+ }
+ currConfObj = eConfObjGlobal;
+ CHKiRet(unsetActionScope());
+ } else {
+ errmsg.LogError(0, RS_RET_INVLD_CONF_OBJ, "invalid config object \"%s\" in $End", pszName);
+ ABORT_FINALIZE(RS_RET_INVLD_CONF_OBJ);
+ }
+
+finalize_it:
+ free(pszName); /* no longer needed */
+ RETiRet;
+}
+
+
+/* Reset config variables to default values. Note that
+ * when we are inside an scope, we simply reset this to global.
+ * However, $ResetConfigVariables is a global directive, and as such
+ * will not be honored inside a scope!
+ * rgerhards, 2010-07-23
+ */
+static rsRetVal
+resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ currConfObj = eConfObjGlobal;
+ bConfStrictScoping = 0;
+ return RS_RET_OK;
+}
+
+
/* exit our class
* rgerhards, 2008-03-11
*/
@@ -1286,6 +1424,11 @@ BEGINAbstractObjClassInit(conf, 1, OBJ_IS_CORE_MODULE) /* class, version - CHANG
CHKiRet(objUse(net, LM_NET_FILENAME)); /* TODO: make this dependcy go away! */
CHKiRet(objUse(rule, CORE_COMPONENT));
CHKiRet(objUse(ruleset, CORE_COMPONENT));
+
+ CHKiRet(regCfSysLineHdlr((uchar *)"begin", 0, eCmdHdlrGetWord, beginConfObj, NULL, NULL, eConfObjGlobal));
+ CHKiRet(regCfSysLineHdlr((uchar *)"end", 0, eCmdHdlrGetWord, endConfObj, NULL, NULL, eConfObjAlways));
+ CHKiRet(regCfSysLineHdlr((uchar *)"strictscoping", 0, eCmdHdlrBinary, NULL, &bConfStrictScoping, NULL, eConfObjGlobal));
+ CHKiRet(regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, NULL, eConfObjAction));
ENDObjClassInit(conf)
/* vi:set ai:
diff --git a/runtime/conf.h b/runtime/conf.h
index d85d1f82..bc09d502 100644
--- a/runtime/conf.h
+++ b/runtime/conf.h
@@ -28,6 +28,8 @@
* somewhat strange (at least its name). -- rgerhards, 2007-08-01
*/
enum eDirective { DIR_TEMPLATE = 0, DIR_OUTCHANNEL = 1, DIR_ALLOWEDSENDER = 2};
+extern ecslConfObjType currConfObj;
+extern int bConfStrictScoping; /* force strict scoping during config processing? */
/* interfaces */
BEGINinterface(conf) /* name must also be changed in ENDinterface macro! */
@@ -38,8 +40,14 @@ BEGINinterface(conf) /* name must also be changed in ENDinterface macro! */
rsRetVal (*cfline)(uchar *line, rule_t **pfCurr);
rsRetVal (*processConfFile)(uchar *pConfFile);
rsRetVal (*GetNbrActActions)(int *);
+ /* version 4 -- 2010-07-23 rgerhards */
+ /* "just" added global variables
+ * FYI: we reconsider repacking as a non-object, as only the core currently
+ * accesses this module. The current object structure complicates things without
+ * any real benefit.
+ */
ENDinterface(conf)
-#define confCURR_IF_VERSION 3 /* increment whenever you change the interface structure! */
+#define confCURR_IF_VERSION 4 /* increment whenever you change the interface structure! */
/* in Version 3, entry point "ReInitConf()" was removed, as we do not longer need
* to support restart-type HUP -- rgerhards, 2009-07-15
*/
diff --git a/runtime/glbl.c b/runtime/glbl.c
index 278bc4e1..42f02008 100644
--- a/runtime/glbl.c
+++ b/runtime/glbl.c
@@ -346,15 +346,15 @@ BEGINAbstractObjClassInit(glbl, 1, OBJ_IS_CORE_MODULE) /* class, version */
CHKiRet(objUse(prop, CORE_COMPONENT));
/* register config handlers (TODO: we need to implement a way to unregister them) */
- CHKiRet(regCfSysLineHdlr((uchar *)"workdirectory", 0, eCmdHdlrGetWord, NULL, &pszWorkDir, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"dropmsgswithmaliciousdnsptrrecords", 0, eCmdHdlrBinary, NULL, &bDropMalPTRMsgs, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriver", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvr, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercafile", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvrCAF, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriverkeyfile", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvrKeyFile, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercertfile", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvrCertFile, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"optimizeforuniprocessor", 0, eCmdHdlrBinary, NULL, &bOptimizeUniProc, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"preservefqdn", 0, eCmdHdlrBinary, NULL, &bPreserveFQDN, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"workdirectory", 0, eCmdHdlrGetWord, NULL, &pszWorkDir, NULL, eConfObjGlobal));
+ CHKiRet(regCfSysLineHdlr((uchar *)"dropmsgswithmaliciousdnsptrrecords", 0, eCmdHdlrBinary, NULL, &bDropMalPTRMsgs, NULL, eConfObjGlobal));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriver", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvr, NULL, eConfObjGlobal));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercafile", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvrCAF, NULL, eConfObjGlobal));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriverkeyfile", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvrKeyFile, NULL, eConfObjGlobal));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercertfile", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvrCertFile, NULL, eConfObjGlobal));
+ CHKiRet(regCfSysLineHdlr((uchar *)"optimizeforuniprocessor", 0, eCmdHdlrBinary, NULL, &bOptimizeUniProc, NULL, eConfObjGlobal));
+ CHKiRet(regCfSysLineHdlr((uchar *)"preservefqdn", 0, eCmdHdlrBinary, NULL, &bPreserveFQDN, NULL, eConfObjGlobal));
+ CHKiRet(regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, NULL, eConfObjGlobal));
INIT_ATOMIC_HELPER_MUT(mutTerminateInputs);
ENDObjClassInit(glbl)
diff --git a/runtime/glbl.h b/runtime/glbl.h
index 4b4bdf83..82bd1a7a 100644
--- a/runtime/glbl.h
+++ b/runtime/glbl.h
@@ -76,7 +76,7 @@ BEGINinterface(glbl) /* name must also be changed in ENDinterface macro! */
*/
SIMP_PROP(FdSetSize, int)
/* v7: was neeeded to mean v5+v6 - do NOT add anything else for that version! */
- /* next change is v8! */
+ /* next is v8! */
#undef SIMP_PROP
ENDinterface(glbl)
#define glblCURR_IF_VERSION 7 /* increment whenever you change the interface structure! */
diff --git a/runtime/module-template.h b/runtime/module-template.h
index d05ec23c..f0084ea1 100644
--- a/runtime/module-template.h
+++ b/runtime/module-template.h
@@ -35,7 +35,7 @@
/* macro to define standard output-module static data members
*/
#define DEF_MOD_STATIC_DATA \
- static __attribute__((unused)) rsRetVal (*omsdRegCFSLineHdlr)();
+ static __attribute__((unused)) rsRetVal (*omsdRegCFSLineHdlr)(uchar *pCmdName, int bChainingPermitted, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData, void *pOwnerCookie, ecslConfObjType eConfObjType);
#define DEF_OMOD_STATIC_DATA \
DEF_MOD_STATIC_DATA \
@@ -306,6 +306,50 @@ static rsRetVal tryResume(instanceData __attribute__((unused)) *pData)\
}
+/* Config scoping system.
+ * save current config scope and start a new one. Note that we do NOT implement a
+ * stack. Exactly one scope can be saved.
+ * We assume standard naming conventions (local confgSettings_t holds all
+ * config settings and MUST have been defined before this macro is being used!).
+ * Note that initConfVars() must be defined locally as well.
+ */
+#define SCOPING_SUPPORT \
+static rsRetVal initConfVars(void);\
+static configSettings_t cs; /* our current config settings */ \
+static configSettings_t cs_save; /* our saved (scope!) config settings */ \
+static rsRetVal newScope(void) \
+{ \
+ DEFiRet; \
+ memcpy(&cs_save, &cs, sizeof(cs)); \
+ iRet = initConfVars(); \
+ RETiRet; \
+} \
+static rsRetVal restoreScope(void) \
+{ \
+ DEFiRet; \
+ memcpy(&cs, &cs_save, sizeof(cs)); \
+ RETiRet; \
+}
+/* initConfVars()
+ * This entry point is called to check if a module can resume operations. This
+ * happens when a module requested that it be suspended. In suspended state,
+ * the engine periodically tries to resume the module. If that succeeds, normal
+ * processing continues. If not, the module will not be called unless a
+ * tryResume() call succeeds.
+ * Returns RS_RET_OK, if resumption succeeded, RS_RET_SUSPENDED otherwise
+ * rgerhard, 2007-08-02
+ */
+#define BEGINinitConfVars \
+static rsRetVal initConfVars(void)\
+{\
+ DEFiRet;
+
+#define CODESTARTinitConfVars
+
+#define ENDinitConfVars \
+ RETiRet;\
+}
+
/* queryEtryPt()
*/
@@ -358,6 +402,10 @@ static rsRetVal queryEtryPt(uchar *name, rsRetVal (**pEtryPoint)())\
*pEtryPoint = freeInstance;\
} else if(!strcmp((char*) name, "parseSelectorAct")) {\
*pEtryPoint = parseSelectorAct;\
+ } else if(!strcmp((char*) name, "newScope")) {\
+ *pEtryPoint = newScope;\
+ } else if(!strcmp((char*) name, "restoreScope")) {\
+ *pEtryPoint = restoreScope;\
} else if(!strcmp((char*) name, "isCompatibleWithFeature")) {\
*pEtryPoint = isCompatibleWithFeature;\
} else if(!strcmp((char*) name, "tryResume")) {\
@@ -473,6 +521,10 @@ rsRetVal modInit##uniqName(int iIFVersRequested __attribute__((unused)), int *ip
/* now get the obj interface so that we can access other objects */ \
CHKiRet(pObjGetObjInterface(&obj));
+/* do those initializations necessary for scoping */
+#define SCOPINGmodInit \
+ initConfVars();
+
#define ENDmodInit \
finalize_it:\
*pQueryEtryPt = queryEtryPt;\
diff --git a/runtime/modules.c b/runtime/modules.c
index d7362753..73a0012c 100644
--- a/runtime/modules.c
+++ b/runtime/modules.c
@@ -350,8 +350,7 @@ static modInfo_t *GetNxt(modInfo_t *pThis)
/* this function is like GetNxt(), but it returns pointers to
- * modules of specific type only. As we currently deal just with output modules,
- * it is a dummy, to be filled with real code later.
+ * modules of specific type only.
* rgerhards, 2007-07-24
*/
static modInfo_t *GetNxtType(modInfo_t *pThis, eModType_t rqtdType)
@@ -461,6 +460,8 @@ doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_
CHKiRet((*pNew->modQueryEtryPt)((uchar*)"doAction", &pNew->mod.om.doAction));
CHKiRet((*pNew->modQueryEtryPt)((uchar*)"parseSelectorAct", &pNew->mod.om.parseSelectorAct));
CHKiRet((*pNew->modQueryEtryPt)((uchar*)"tryResume", &pNew->tryResume));
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"newScope", &pNew->mod.om.newScope));
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"restoreScope", &pNew->mod.om.restoreScope));
/* try load optional interfaces */
localRet = (*pNew->modQueryEtryPt)((uchar*)"doHUP", &pNew->doHUP);
if(localRet != RS_RET_OK && localRet != RS_RET_MODULE_ENTRY_POINT_NOT_FOUND)
@@ -589,6 +590,8 @@ static void modPrintList(void)
dbgprintf("\tparseSelectorAct: 0x%lx\n", (unsigned long) pMod->mod.om.parseSelectorAct);
dbgprintf("\ttryResume: 0x%lx\n", (unsigned long) pMod->tryResume);
dbgprintf("\tdoHUP: 0x%lx\n", (unsigned long) pMod->doHUP);
+ dbgprintf("\tnewScope: 0x%lx\n", (unsigned long) pMod->mod.om.newScope);
+ dbgprintf("\trestoreScope: 0x%lx\n", (unsigned long) pMod->mod.om.restoreScope);
dbgprintf("\tBeginTransaction: 0x%lx\n", (unsigned long)
((pMod->mod.om.beginTransaction == dummyBeginTransaction) ?
0 : pMod->mod.om.beginTransaction));
diff --git a/runtime/modules.h b/runtime/modules.h
index 49586e8d..9569512b 100644
--- a/runtime/modules.h
+++ b/runtime/modules.h
@@ -47,8 +47,10 @@
* version 5 changes the way parsing works for input modules. This is
* an important change, parseAndSubmitMessage() goes away. Other
* module types are not affected. -- rgerhards, 2008-10-09
+ * version 6 introduces scoping support (starting with the output
+ * modules) -- rgerhards, 2010-07-27
*/
-#define CURR_MOD_IF_VERSION 5
+#define CURR_MOD_IF_VERSION 6
typedef enum eModType_ {
eMOD_IN = 0, /* input module */
@@ -117,6 +119,8 @@ struct modInfo_s {
rsRetVal (*doAction)(uchar**, unsigned, void*);
rsRetVal (*endTransaction)(void*);
rsRetVal (*parseSelectorAct)(uchar**, void**,omodStringRequest_t**);
+ rsRetVal (*newScope)(void);
+ rsRetVal (*restoreScope)(void);
} om;
struct { /* data for library modules */
} lm;
diff --git a/runtime/parser.c b/runtime/parser.c
index 40374ae1..f1a4bbf4 100644
--- a/runtime/parser.c
+++ b/runtime/parser.c
@@ -697,12 +697,12 @@ BEGINObjClassInit(parser, 1, OBJ_IS_CORE_MODULE) /* class, version */
CHKiRet(objUse(datetime, CORE_COMPONENT));
CHKiRet(objUse(ruleset, CORE_COMPONENT));
- CHKiRet(regCfSysLineHdlr((uchar *)"controlcharacterescapeprefix", 0, eCmdHdlrGetChar, NULL, &cCCEscapeChar, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"droptrailinglfonreception", 0, eCmdHdlrBinary, NULL, &bDropTrailingLF, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactersonreceive", 0, eCmdHdlrBinary, NULL, &bEscapeCCOnRcv, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"escape8bitcharactersonreceive", 0, eCmdHdlrBinary, NULL, &bEscape8BitChars, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactertab", 0, eCmdHdlrBinary, NULL, &bEscapeTab, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"controlcharacterescapeprefix", 0, eCmdHdlrGetChar, NULL, &cCCEscapeChar, NULL, eConfObjGlobal));
+ CHKiRet(regCfSysLineHdlr((uchar *)"droptrailinglfonreception", 0, eCmdHdlrBinary, NULL, &bDropTrailingLF, NULL, eConfObjGlobal));
+ CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactersonreceive", 0, eCmdHdlrBinary, NULL, &bEscapeCCOnRcv, NULL, eConfObjGlobal));
+ CHKiRet(regCfSysLineHdlr((uchar *)"escape8bitcharactersonreceive", 0, eCmdHdlrBinary, NULL, &bEscape8BitChars, NULL, eConfObjGlobal));
+ CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactertab", 0, eCmdHdlrBinary, NULL, &bEscapeTab, NULL, eConfObjGlobal));
+ CHKiRet(regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, NULL, eConfObjGlobal));
InitParserList(&pParsLstRoot);
InitParserList(&pDfltParsLst);
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index 34eaedca..cb77cbfa 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -201,6 +201,38 @@ typedef enum {
FIOP_EREREGEX = 5 /* matches a ERE regular expression? */
} fiop_t;
+/* types of configuration handlers
+ */
+typedef enum cslCmdHdlrType {
+ eCmdHdlrInvalid = 0, /* invalid handler type - indicates a coding error */
+ eCmdHdlrCustomHandler, /* custom handler, just call handler function */
+ eCmdHdlrUID,
+ eCmdHdlrGID,
+ eCmdHdlrBinary,
+ eCmdHdlrFileCreateMode,
+ eCmdHdlrInt,
+ eCmdHdlrSize,
+ eCmdHdlrGetChar,
+ eCmdHdlrFacility,
+ eCmdHdlrSeverity,
+ eCmdHdlrGetWord
+} ecslCmdHdrlType;
+
+
+/* the next type describes $Begin .. $End block object types
+ */
+typedef enum cslConfObjType {
+ eConfObjGlobal = 0, /* global directives */
+ eConfObjAction, /* action-specific directives */
+ /* now come states that indicate that we wait for a block-end. These are
+ * states that permit us to do some safety checks and they hopefully ease
+ * migration to a "real" parser/grammar.
+ */
+ eConfObjActionWaitEnd,
+ eConfObjAlways /* always valid, very special case (guess $End only!) */
+} ecslConfObjType;
+
+
/* multi-submit support.
* This is done via a simple data structure, which holds the number of elements
@@ -450,10 +482,16 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
RS_RET_TIMEOUT = -2164, /**< timeout occured during operation */
RS_RET_RCV_ERR = -2165, /**< error occured during socket rcv operation */
RS_RET_NO_SOCK_CONFIGURED = -2166, /**< no socket (name) was configured where one is required */
+ RS_RET_CONF_NOT_GLBL = -2167, /**< $Begin not in global scope */
+ RS_RET_CONF_IN_GLBL = -2168, /**< $End when in global scope */
+ RS_RET_CONF_INVLD_END = -2169, /**< $End for wrong conf object (probably nesting error) */
+ RS_RET_CONF_INVLD_SCOPE = -2170,/**< config statement not valid in current scope (e.g. global stmt in action block) */
+ RS_RET_CONF_END_NO_ACT = -2171, /**< end of action block, but no actual action specified */
RS_RET_NO_LSTN_DEFINED = -2172, /**< no listener defined (e.g. inside an input module) */
RS_RET_EPOLL_CR_FAILED = -2173, /**< epoll_create() failed */
RS_RET_EPOLL_CTL_FAILED = -2174, /**< epoll_ctl() failed */
RS_RET_INTERNAL_ERROR = -2175, /**< rsyslogd internal error, unexpected code path reached */
+ RS_RET_INVLD_CONF_OBJ= -2176, /**< invalid config object (e.g. $Begin conf statement) */
/* RainerScript error messages (range 1000.. 1999) */
RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */
@@ -573,6 +611,13 @@ rsRetVal rsrtExit(void);
int rsrtIsInit(void);
rsRetVal rsrtSetErrLogger(rsRetVal (*errLogger)(int, uchar*));
+/* this define below is (later) intended to be used to implement empty
+ * structs. TODO: check if compilers supports this and, if not, define
+ * a dummy variable. This requires review of where in code empty structs
+ * are already defined. -- rgerhards, 2010-07-26
+ */
+#define EMPTY_STRUCT
+
#endif /* multi-include protection */
/* vim:set ai:
*/
diff --git a/runtime/ruleset.c b/runtime/ruleset.c
index 0584e8d6..8162c752 100644
--- a/runtime/ruleset.c
+++ b/runtime/ruleset.c
@@ -623,8 +623,8 @@ BEGINObjClassInit(ruleset, 1, OBJ_IS_CORE_MODULE) /* class, version */
CHKiRet(llInit(&llRulesets, rulesetDestructForLinkedList, keyDestruct, strcasecmp));
/* config file handlers */
- CHKiRet(regCfSysLineHdlr((uchar *)"rulesetparser", 0, eCmdHdlrGetWord, rulesetAddParser, NULL, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"rulesetcreatemainqueue", 0, eCmdHdlrBinary, rulesetCreateQueue, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"rulesetparser", 0, eCmdHdlrGetWord, rulesetAddParser, NULL, NULL, eConfObjGlobal));
+ CHKiRet(regCfSysLineHdlr((uchar *)"rulesetcreatemainqueue", 0, eCmdHdlrBinary, rulesetCreateQueue, NULL, NULL, eConfObjGlobal));
ENDObjClassInit(ruleset)
/* vi:set ai: