diff options
-rw-r--r-- | action.c | 23 | ||||
-rw-r--r-- | doc/pmlastmsg.html | 4 | ||||
-rw-r--r-- | runtime/rsconf.c | 1 | ||||
-rw-r--r-- | runtime/rsyslog.h | 1 | ||||
-rw-r--r-- | tools/omfile.c | 198 |
5 files changed, 176 insertions, 51 deletions
@@ -1942,6 +1942,7 @@ actionNewInst(struct nvlst *lst, action_t **ppAction) uchar *cnfModName = NULL; omodStringRequest_t *pOMSR; void *pModData; + action_t *pAction; DEFiRet; paramvals = nvlstGetParams(lst, ¶mblk, NULL); @@ -1959,9 +1960,25 @@ actionNewInst(struct nvlst *lst, action_t **ppAction) errmsg.LogError(0, RS_RET_MOD_UNKNOWN, "module name '%s' is unknown", cnfModName); ABORT_FINALIZE(RS_RET_MOD_UNKNOWN); } -dbgprintf("XXXX:actionNewInst for module '%s'/%p\n", cnfModName, pMod); - CHKiRet(pMod->mod.om.newActInst(cnfModName, lst, &pModData, &pOMSR)); -dbgprintf("XXXX:actionNewInst CALLED module '%s'/%p\n", cnfModName, pMod); + iRet = pMod->mod.om.newActInst(cnfModName, lst, &pModData, &pOMSR); + // TODO: check if RS_RET_SUSPENDED is still valid in v6! + if(iRet != RS_RET_OK && iRet != RS_RET_SUSPENDED) { + FINALIZE; /* iRet is already set to error state */ + } + + 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) + pAction->f_ReduceRepeated = loadConf->globals.bReduceRepeatMsgs; + else { + DBGPRINTF("module is incompatible with RepeatedMsgReduction - turned off\n"); + pAction->f_ReduceRepeated = 0; + } + pAction->eState = ACT_STATE_RDY; /* action is enabled */ + loadConf->actions.nbrActions++; /* one more active action! */ + } + *ppAction = pAction; + finalize_it: free(cnfModName); cnfparamvalsDestruct(paramvals, ¶mblk); diff --git a/doc/pmlastmsg.html b/doc/pmlastmsg.html index 247178c3..fd26dbd5 100644 --- a/doc/pmlastmsg.html +++ b/doc/pmlastmsg.html @@ -30,7 +30,9 @@ where n must be an integer. All other messages are left untouched. <p><b>Please note:</b> this parser module makes it possible that these messages are properly detected. It does <b>not</b> drop them. If you intend to drop those messages, you need to use the usual filter logic in combination with the discard -action. +action. As a side-note, please keep on your mind that the sender discarded messages +when the "last message repeated n times" message is emited. You want to consider if +that really is what you intend to happen. If not, go change the sender. <p><b>Configuration Directives</b>:</p> <p>There do not currently exist any configuration directives for this module. diff --git a/runtime/rsconf.c b/runtime/rsconf.c index f93bd7bc..e85597f8 100644 --- a/runtime/rsconf.c +++ b/runtime/rsconf.c @@ -232,6 +232,7 @@ cnfDoActlst(struct cnfactlst *actlst, rule_t *pRule) if(actlst->actType == CNFACT_V2) { dbgprintf("v6+ action object\n"); actionNewInst(actlst->data.lst, &pAction); + iRet = llAppend(&(pRule)->llActList, NULL, (void*) pAction); } else { dbgprintf("legacy action line:%s\n", actlst->data.legActLine); str = (uchar*) actlst->data.legActLine; diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h index dd770f26..c2dbc2b2 100644 --- a/runtime/rsyslog.h +++ b/runtime/rsyslog.h @@ -364,6 +364,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth RS_RET_CONF_RQRD_PARAM_MISSING = -2208,/**< required parameter in config object is missing */ RS_RET_MOD_UNKNOWN = -2209,/**< module (config name) is unknown */ RS_RET_CONFOBJ_UNSUPPORTED = -2210,/**< config objects (v6 conf) are not supported here */ + RS_RET_MISSING_CNFPARAMS = -2211, /**< missing configuration parameters */ /* RainerScript error messages (range 1000.. 1999) */ RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */ diff --git a/tools/omfile.c b/tools/omfile.c index 8d332ee9..22dacc8a 100644 --- a/tools/omfile.c +++ b/tools/omfile.c @@ -128,9 +128,9 @@ typedef struct s_dynaFileCacheEntry dynaFileCacheEntry; typedef struct _instanceData { - uchar f_fname[MAXFNAME];/* file or template name (display only) */ + uchar *f_fname; /* file or template name (display only) */ + uchar *tplName; /* name of assigned template */ strm_t *pStrm; /* our output stream */ - strmType_t strmType; /* stream type, used for named pipes */ char bDynamicName; /* 0 - static name, 1 - dynamic name (with properties) */ int fCreateMode; /* file creation mode for open() */ int fDirCreateMode; /* creation mode for mkdir() */ @@ -181,6 +181,36 @@ uchar *pszFileDfltTplName; /* name of the default template to use */ SCOPING_SUPPORT; /* must be set AFTER configSettings_t is defined */ +/* tables for interfacing with the v6 config system */ +/* action (instance) parameters */ +static struct cnfparamdescr actpdescr[] = { + { "dynafilecachesize", eCmdHdlrInt, 0 }, /* legacy: dynafilecachesize */ + { "ziplevel", eCmdHdlrInt, 0 }, /* legacy: omfileziplevel */ + { "flushinterval", eCmdHdlrInt, 0 }, /* legacy: omfileflushinterval */ + { "asyncwriting", eCmdHdlrBinary, 0 }, /* legacy: omfileasyncwriting */ + { "flushontxend", eCmdHdlrBinary, 0 }, /* legacy: omfileflushontxend */ + { "iobuffersize", eCmdHdlrSize, 0 }, /* legacy: omfileiobuffersize */ + { "dirowner", eCmdHdlrUID, 0 }, /* legacy: dirowner */ + { "dirgroup", eCmdHdlrGID, 0 }, /* legacy: dirgroup */ + { "fileowner", eCmdHdlrUID, 0 }, /* legacy: fileowner */ + { "filegroup", eCmdHdlrGID, 0 }, /* legacy: filegroup */ + { "dircreatemode", eCmdHdlrFileCreateMode, 0 }, /* legacy: dircreatemode */ + { "filecreatemode", eCmdHdlrFileCreateMode, 0 }, /* legacy: filecreatemode */ + { "failonchownfailure", eCmdHdlrBinary, 0 }, /* legacy: failonchownfailure */ + { "createdirs", eCmdHdlrBinary, 0 }, /* legacy: createdirs */ + { "sync", eCmdHdlrBinary, 0 }, /* legacy: actionfileenablesync */ + { "file", eCmdHdlrString, 0 }, /* either "file" or ... */ + { "dynafile", eCmdHdlrString, 0 }, /* "dynafile" MUST be present */ + { "template", eCmdHdlrGetWord, 0 }, + //{ "", eCmdHdlrGetWord, 0 }, /* legacy: */ +}; +static struct cnfparamblk actpblk = + { CNFPARAMBLK_VERSION, + sizeof(actpdescr)/sizeof(struct cnfparamdescr), + actpdescr + }; + + BEGINinitConfVars /* (re)set config variables to default values */ CODESTARTinitConfVars pszFileDfltTplName = NULL; /* make sure this can be free'ed! */ @@ -297,7 +327,7 @@ static rsRetVal cflineParseOutchannel(instanceData *pData, uchar* p, omodStringR } /* OK, we finally got a correct template. So let's use it... */ - ustrncpy(pData->f_fname, pOch->pszFileTemplate, MAXFNAME); + pData->f_fname = ustrdup(pOch->pszFileTemplate); pData->iSizeLimit = pOch->uSizeLimit; /* WARNING: It is dangerous "just" to pass the pointer. As we * never rebuild the output channel description, this is acceptable here. @@ -454,7 +484,7 @@ prepareFile(instanceData *pData, uchar *newFileName) CHKiRet(strm.SettOperationsMode(pData->pStrm, STREAMMODE_WRITE_APPEND)); CHKiRet(strm.SettOpenMode(pData->pStrm, cs.fCreateMode)); CHKiRet(strm.SetbSync(pData->pStrm, pData->bSyncFile)); - CHKiRet(strm.SetsType(pData->pStrm, pData->strmType)); + CHKiRet(strm.SetsType(pData->pStrm, STREAMTYPE_FILE_SINGLE)); CHKiRet(strm.SetiSizeLimit(pData->pStrm, pData->iSizeLimit)); /* set the flush interval only if we actually use it - otherwise it will activate * async processing, which is a real performance waste if we do not do buffered @@ -654,11 +684,8 @@ writeFile(uchar **ppString, unsigned iMsgOpts, instanceData *pData) finalize_it: if(iRet != RS_RET_OK) { - /* in v5, we shall return different states for message-caused failure (but only there!) */ - if(pData->strmType == STREAMTYPE_NAMED_PIPE) - iRet = RS_RET_DISABLE_ACTION; /* this is the traditional semantic -- rgerhards, 2010-01-15 */ - else - iRet = RS_RET_SUSPENDED; + + iRet = RS_RET_SUSPENDED; } RETiRet; } @@ -672,6 +699,7 @@ ENDcreateInstance BEGINfreeInstance CODESTARTfreeInstance + free(pData->f_fname); if(pData->bDynamicName) { dynaFileFreeCache(pData); } else if(pData->pStrm != NULL) @@ -711,20 +739,121 @@ finalize_it: ENDdoAction +static inline void +setInstParamDefaults(instanceData *pData) +{ + pData->f_fname = NULL; + pData->tplName = NULL; + pData->fileUID = -1; + pData->fileGID = -1; + pData->dirUID = -1; + pData->dirGID = -1; + pData->bFailOnChown = 1; + pData->iDynaFileCacheSize = 10; + pData->fCreateMode = 0644; + pData->fDirCreateMode = 0700; + pData->bCreateDirs = 1; + pData->bSyncFile = 0; + pData->iZipLevel = 0; + pData->bFlushOnTXEnd = FLUSHONTX_DFLT; + pData->iIOBufSize = IOBUF_DFLT_SIZE; + pData->iFlushInterval = FLUSH_INTRVL_DFLT; + pData->bUseAsyncWriter = USE_ASYNCWRITER_DFLT; +} + BEGINnewActInst + struct cnfparamvals *pvals; + int i; CODESTARTnewActInst - // TODO: valid lst params dbgprintf("XXXX: in newActInst (omfile)\n"); -#if 0 + + pvals = nvlstGetParams(lst, &actpblk, NULL); + if(pvals == NULL) { + errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, "omfile: either the \"file\" or " + "\"dynfile\" parameter must be given"); + ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); + } + + if(Debug) { + dbgprintf("action param blk in omfile:\n"); + cnfparamsPrint(&actpblk, pvals); + } + CHKiRet(createInstance(&pData)); + setInstParamDefaults(pData); + + for(i = 0 ; i < actpblk.nParams ; ++i) { + if(!pvals[i].bUsed) + continue; + if(!strcmp(actpblk.descr[i].name, "dynafilecachesize")) { + pData->iDynaFileCacheSize = (int) pvals[i].val.d.n; + } else if(!strcmp(actpblk.descr[i].name, "ziplevel")) { + pData->iZipLevel = (int) pvals[i].val.d.n; + } else if(!strcmp(actpblk.descr[i].name, "flushinterval")) { + pData->iFlushInterval = pvals[i].val.d.n; + } else if(!strcmp(actpblk.descr[i].name, "asyncwriting")) { + pData->bUseAsyncWriter = pvals[i].val.d.n; + } else if(!strcmp(actpblk.descr[i].name, "flushontxend")) { + pData->bFlushOnTXEnd = pvals[i].val.d.n; + } else if(!strcmp(actpblk.descr[i].name, "iobuffersize")) { + pData->iIOBufSize = (int) pvals[i].val.d.n; + } else if(!strcmp(actpblk.descr[i].name, "dirowner")) { + pData->dirUID = (int) pvals[i].val.d.n; + } else if(!strcmp(actpblk.descr[i].name, "dirgroup")) { + pData->dirGID = (int) pvals[i].val.d.n; + } else if(!strcmp(actpblk.descr[i].name, "fileowner")) { + pData->fileUID = (int) pvals[i].val.d.n; + } else if(!strcmp(actpblk.descr[i].name, "filegroup")) { + pData->fileGID = (int) pvals[i].val.d.n; + } else if(!strcmp(actpblk.descr[i].name, "dircreatemode")) { + pData->fDirCreateMode = (int) pvals[i].val.d.n; + } else if(!strcmp(actpblk.descr[i].name, "filecreatemode")) { + pData->fCreateMode = (int) pvals[i].val.d.n; + } else if(!strcmp(actpblk.descr[i].name, "failonchownfailure")) { + pData->bFailOnChown = (int) pvals[i].val.d.n; + } else if(!strcmp(actpblk.descr[i].name, "sync")) { + pData->bSyncFile = (int) pvals[i].val.d.n; + } else if(!strcmp(actpblk.descr[i].name, "createdirs")) { + pData->bCreateDirs = (int) pvals[i].val.d.n; + } else if(!strcmp(actpblk.descr[i].name, "file")) { + pData->f_fname = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + CODE_STD_STRING_REQUESTnewActInst(1) + pData->bDynamicName = 0; + } else if(!strcmp(actpblk.descr[i].name, "dynafile")) { + pData->f_fname = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + CODE_STD_STRING_REQUESTnewActInst(2) + pData->bDynamicName = 1; + } else if(!strcmp(actpblk.descr[i].name, "template")) { + pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else { + dbgprintf("omfile: program error, non-handled " + "param '%s'\n", actpblk.descr[i].name); + } + } - if(*p == '-') { - pData->bSyncFile = 0; - p++; - } else { - pData->bSyncFile = cs.bEnableSync; + if(pData->f_fname == NULL) { + errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, "omfile: either the \"file\" or " + "\"dynfile\" parameter must be given"); + ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } + CHKiRet(OMSRsetEntry(*ppOMSR, 0, ustrdup((pData->tplName == NULL) ? + (uchar*)"RSYSLOG_FileFormat" : (uchar*)"??"), + OMSR_NO_RQD_TPL_OPTS)); + + if(pData->bDynamicName) { + /* "filename" is actually a template name, we need this as string 1. So let's add it + * to the pOMSR. -- rgerhards, 2007-07-27 + */ + CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(pData->f_fname), OMSR_NO_RQD_TPL_OPTS)); + // TODO: create unified code for this (legacy+v6 system) + /* we now allocate the cache table */ + CHKmalloc(pData->dynCache = (dynaFileCacheEntry**) + calloc(cs.iDynaFileCacheSize, sizeof(dynaFileCacheEntry*))); + pData->iCurrElt = -1; /* no current element */ + } +// TODO: add pData->iSizeLimit = 0; /* default value, use outchannels to configure! */ +#if 0 switch(*p) { case '$': CODE_STD_STRING_REQUESTnewActInst(1) @@ -757,41 +886,15 @@ CODESTARTnewActInst CHKmalloc(pData->dynCache = (dynaFileCacheEntry**) calloc(cs.iDynaFileCacheSize, sizeof(dynaFileCacheEntry*))); break; - - case '/': - case '.': - CODE_STD_STRING_REQUESTnewActInst(1) - pData->strmType = STREAMTYPE_FILE_SINGLE; - CHKiRet(cflineParseFileName(p, (uchar*) pData->f_fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, - (pszFileDfltTplName == NULL) ? (uchar*)"RSYSLOG_FileFormat" : pszFileDfltTplName)); - pData->bDynamicName = 0; - break; - default: - ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED); } - - /* freeze current paremeters for this action */ - pData->iSizeLimit = 0; /* default value, use outchannels to configure! */ - pData->iDynaFileCacheSize = cs.iDynaFileCacheSize; - pData->fCreateMode = cs.fCreateMode; - pData->fDirCreateMode = cs.fDirCreateMode; - pData->bCreateDirs = cs.bCreateDirs; - pData->bFailOnChown = cs.bFailOnChown; - pData->fileUID = cs.fileUID; - pData->fileGID = cs.fileGID; - pData->dirUID = cs.dirUID; - pData->dirGID = cs.dirGID; - pData->iZipLevel = cs.iZipLevel; - pData->bFlushOnTXEnd = cs.bFlushOnTXEnd; - pData->iIOBufSize = (int) cs.iIOBufSize; - pData->iFlushInterval = cs.iFlushInterval; - pData->bUseAsyncWriter = cs.bUseAsyncWriter; #endif CODE_STD_FINALIZERnewActInst + cnfparamvalsDestruct(pvals, &actpblk); ENDnewActInst BEGINparseSelectorAct + uchar fname[MAXFNAME]; CODESTARTparseSelectorAct /* Note: the indicator sequence permits us to use '$' to signify * outchannel, what otherwise is not possible due to truely @@ -833,13 +936,14 @@ CODESTARTparseSelectorAct */ CODE_STD_STRING_REQUESTparseSelectorAct(2) ++p; /* eat '?' */ - CHKiRet(cflineParseFileName(p, (uchar*) pData->f_fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, + CHKiRet(cflineParseFileName(p, fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (pszFileDfltTplName == NULL) ? (uchar*)"RSYSLOG_FileFormat" : pszFileDfltTplName)); /* "filename" is actually a template name, we need this as string 1. So let's add it * to the pOMSR. -- rgerhards, 2007-07-27 */ CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(pData->f_fname), OMSR_NO_RQD_TPL_OPTS)); + pData->f_fname = ustrdup(fname); pData->bDynamicName = 1; pData->iCurrElt = -1; /* no current element */ /* we now allocate the cache table */ @@ -850,9 +954,9 @@ CODESTARTparseSelectorAct case '/': case '.': CODE_STD_STRING_REQUESTparseSelectorAct(1) - pData->strmType = STREAMTYPE_FILE_SINGLE; - CHKiRet(cflineParseFileName(p, (uchar*) pData->f_fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, + CHKiRet(cflineParseFileName(p, fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (pszFileDfltTplName == NULL) ? (uchar*)"RSYSLOG_FileFormat" : pszFileDfltTplName)); + pData->f_fname = ustrdup(fname); pData->bDynamicName = 0; break; default: |