mirror of
https://github.com/rsyslog/rsyslog.git
synced 2025-12-19 19:40:41 +01:00
cleaup & emergency config system reactivated
This commit is contained in:
parent
6ebf9ada25
commit
5e2b03a31c
@ -198,6 +198,29 @@ int fileno(FILE *stream);
|
||||
<<EOF>> { if(popfile() != 0) yyterminate(); }
|
||||
|
||||
%%
|
||||
int
|
||||
cnfParseBuffer(char *buf, unsigned lenBuf)
|
||||
{
|
||||
struct bufstack *bs;
|
||||
int r = 0;
|
||||
/* maintain stack */
|
||||
if((bs = malloc(sizeof(struct bufstack))) == NULL) {
|
||||
r = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if(currbs != NULL)
|
||||
currbs->lineno = yylineno;
|
||||
bs->prev = currbs;
|
||||
bs->fn = strdup("*buffer*");
|
||||
bs->bs = yy_scan_buffer(buf, lenBuf);
|
||||
bs->estr = NULL;
|
||||
currbs = bs;
|
||||
currfn = bs->fn;
|
||||
yylineno = 1;
|
||||
done: return r;
|
||||
}
|
||||
|
||||
/* set a new buffers. Returns 0 on success, something else otherwise. */
|
||||
int
|
||||
cnfSetLexFile(char *fname)
|
||||
|
||||
@ -166,6 +166,7 @@ struct exprret {
|
||||
};
|
||||
|
||||
|
||||
int cnfParseBuffer(char *buf, unsigned lenBuf);
|
||||
void readConfFile(FILE *fp, es_str_t **str);
|
||||
struct nvlst* nvlstNew(es_str_t *name, es_str_t *value);
|
||||
void nvlstDestruct(struct nvlst *lst);
|
||||
|
||||
257
runtime/conf.c
257
runtime/conf.c
@ -79,7 +79,6 @@
|
||||
|
||||
/* forward definitions */
|
||||
static rsRetVal cfline(rsconf_t *conf, uchar *line, rule_t **pfCurr);
|
||||
static rsRetVal processConfFile(rsconf_t *conf, uchar *pConfFile);
|
||||
|
||||
|
||||
/* static data */
|
||||
@ -109,146 +108,6 @@ cstr_t *pDfltHostnameCmp = NULL;
|
||||
cstr_t *pDfltProgNameCmp = NULL;
|
||||
|
||||
|
||||
/* process a directory and include all of its files into
|
||||
* the current config file. There is no specific order of inclusion,
|
||||
* files are included in the order they are read from the directory.
|
||||
* The caller must have make sure that the provided parameter is
|
||||
* indeed a directory.
|
||||
* rgerhards, 2007-08-01
|
||||
*/
|
||||
static rsRetVal doIncludeDirectory(rsconf_t *conf, uchar *pDirName)
|
||||
{
|
||||
DEFiRet;
|
||||
int iEntriesDone = 0;
|
||||
DIR *pDir;
|
||||
union {
|
||||
struct dirent d;
|
||||
char b[offsetof(struct dirent, d_name) + NAME_MAX + 1];
|
||||
} u;
|
||||
struct dirent *res;
|
||||
size_t iDirNameLen;
|
||||
size_t iFileNameLen;
|
||||
uchar szFullFileName[MAXFNAME];
|
||||
|
||||
ASSERT(pDirName != NULL);
|
||||
|
||||
if((pDir = opendir((char*) pDirName)) == NULL) {
|
||||
errmsg.LogError(errno, RS_RET_FOPEN_FAILURE, "error opening include directory");
|
||||
ABORT_FINALIZE(RS_RET_FOPEN_FAILURE);
|
||||
}
|
||||
|
||||
/* prepare file name buffer */
|
||||
iDirNameLen = strlen((char*) pDirName);
|
||||
memcpy(szFullFileName, pDirName, iDirNameLen);
|
||||
|
||||
/* now read the directory */
|
||||
iEntriesDone = 0;
|
||||
while(readdir_r(pDir, &u.d, &res) == 0) {
|
||||
if(res == NULL)
|
||||
break; /* this also indicates end of directory */
|
||||
# ifdef DT_REG
|
||||
/* TODO: find an alternate way to checking for special files if this is
|
||||
* not defined. This is currently a known problem on HP UX, but the work-
|
||||
* around is simple: do not create special files in that directory. So
|
||||
* fixing this is actually not the most important thing on earth...
|
||||
* rgerhards, 2008-03-04
|
||||
*/
|
||||
if(res->d_type != DT_REG)
|
||||
continue; /* we are not interested in special files */
|
||||
# endif
|
||||
if(res->d_name[0] == '.')
|
||||
continue; /* these files we are also not interested in */
|
||||
++iEntriesDone;
|
||||
/* construct filename */
|
||||
iFileNameLen = strlen(res->d_name);
|
||||
if (iFileNameLen > NAME_MAX)
|
||||
iFileNameLen = NAME_MAX;
|
||||
memcpy(szFullFileName + iDirNameLen, res->d_name, iFileNameLen);
|
||||
*(szFullFileName + iDirNameLen + iFileNameLen) = '\0';
|
||||
dbgprintf("including file '%s'\n", szFullFileName);
|
||||
processConfFile(conf, szFullFileName);
|
||||
/* we deliberately ignore the iRet of processConfFile() - this is because
|
||||
* failure to process one file does not mean all files will fail. By ignoring,
|
||||
* we retry with the next file, which is the best thing we can do. -- rgerhards, 2007-08-01
|
||||
*/
|
||||
}
|
||||
|
||||
if(iEntriesDone == 0) {
|
||||
/* I just make it a debug output, because I can think of a lot of cases where it
|
||||
* makes sense not to have any files. E.g. a system maintainer may place a $Include
|
||||
* into the config file just in case, when additional modules be installed. When none
|
||||
* are installed, the directory will be empty, which is fine. -- rgerhards 2007-08-01
|
||||
*/
|
||||
dbgprintf("warning: the include directory contained no files - this may be ok.\n");
|
||||
}
|
||||
|
||||
finalize_it:
|
||||
if(pDir != NULL)
|
||||
closedir(pDir);
|
||||
|
||||
RETiRet;
|
||||
}
|
||||
|
||||
|
||||
/* process a $include config line. That type of line requires
|
||||
* inclusion of another file.
|
||||
* rgerhards, 2007-08-01
|
||||
*/
|
||||
rsRetVal
|
||||
doIncludeLine(rsconf_t *conf, uchar **pp, __attribute__((unused)) void* pVal)
|
||||
{
|
||||
DEFiRet;
|
||||
char pattern[MAXFNAME];
|
||||
uchar *cfgFile;
|
||||
glob_t cfgFiles;
|
||||
int result;
|
||||
size_t i = 0;
|
||||
struct stat fileInfo;
|
||||
|
||||
ASSERT(pp != NULL);
|
||||
ASSERT(*pp != NULL);
|
||||
|
||||
if(getSubString(pp, (char*) pattern, sizeof(pattern) / sizeof(char), ' ') != 0) {
|
||||
errmsg.LogError(0, RS_RET_NOT_FOUND, "could not parse config file name");
|
||||
ABORT_FINALIZE(RS_RET_NOT_FOUND);
|
||||
}
|
||||
|
||||
/* Use GLOB_MARK to append a trailing slash for directories.
|
||||
* Required by doIncludeDirectory().
|
||||
*/
|
||||
result = glob(pattern, GLOB_MARK, NULL, &cfgFiles);
|
||||
if(result == GLOB_NOSPACE || result == GLOB_ABORTED) {
|
||||
char errStr[1024];
|
||||
rs_strerror_r(errno, errStr, sizeof(errStr));
|
||||
errmsg.LogError(0, RS_RET_FILE_NOT_FOUND, "error accessing config file or directory '%s': %s",
|
||||
pattern, errStr);
|
||||
ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
for(i = 0; i < cfgFiles.gl_pathc; i++) {
|
||||
cfgFile = (uchar*) cfgFiles.gl_pathv[i];
|
||||
|
||||
if(stat((char*) cfgFile, &fileInfo) != 0)
|
||||
continue; /* continue with the next file if we can't stat() the file */
|
||||
|
||||
if(S_ISREG(fileInfo.st_mode)) { /* config file */
|
||||
dbgprintf("requested to include config file '%s'\n", cfgFile);
|
||||
iRet = processConfFile(conf, cfgFile);
|
||||
} else if(S_ISDIR(fileInfo.st_mode)) { /* config directory */
|
||||
dbgprintf("requested to include directory '%s'\n", cfgFile);
|
||||
iRet = doIncludeDirectory(conf, cfgFile);
|
||||
} else { /* TODO: shall we handle symlinks or not? */
|
||||
dbgprintf("warning: unable to process IncludeConfig directive '%s'\n", cfgFile);
|
||||
}
|
||||
}
|
||||
|
||||
globfree(&cfgFiles);
|
||||
|
||||
finalize_it:
|
||||
RETiRet;
|
||||
}
|
||||
|
||||
|
||||
/* process a $ModLoad config line. */
|
||||
rsRetVal
|
||||
doModLoad(uchar **pp, __attribute__((unused)) void* pVal)
|
||||
@ -389,120 +248,6 @@ finalize_it:
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* process a configuration file
|
||||
* started with code from init() by rgerhards on 2007-07-31
|
||||
*/
|
||||
static rsRetVal
|
||||
processConfFile(rsconf_t *conf, uchar *pConfFile)
|
||||
{
|
||||
int iLnNbr = 0;
|
||||
FILE *cf;
|
||||
rule_t *pCurrRule = NULL;
|
||||
uchar *p;
|
||||
uchar cbuf[CFGLNSIZ];
|
||||
uchar *cline;
|
||||
int i;
|
||||
int bHadAnError = 0;
|
||||
uchar *pszOrgLine = NULL;
|
||||
size_t lenLine;
|
||||
DEFiRet;
|
||||
ASSERT(pConfFile != NULL);
|
||||
|
||||
if((cf = fopen((char*)pConfFile, "r")) == NULL) {
|
||||
ABORT_FINALIZE(RS_RET_FOPEN_FAILURE);
|
||||
}
|
||||
|
||||
/* Now process the file.
|
||||
*/
|
||||
cline = cbuf;
|
||||
while (fgets((char*)cline, sizeof(cbuf) - (cline - cbuf), cf) != NULL) {
|
||||
++iLnNbr;
|
||||
/* drop LF - TODO: make it better, replace fgets(), but its clean as it is */
|
||||
lenLine = ustrlen(cline);
|
||||
if(cline[lenLine-1] == '\n') {
|
||||
cline[lenLine-1] = '\0';
|
||||
}
|
||||
free(pszOrgLine);
|
||||
pszOrgLine = ustrdup(cline); /* save if needed for errmsg, NULL ptr is OK */
|
||||
/* check for end-of-section, comments, strip off trailing
|
||||
* spaces and newline character.
|
||||
*/
|
||||
p = cline;
|
||||
skipWhiteSpace(&p);
|
||||
if (*p == '\0' || *p == '#')
|
||||
continue;
|
||||
|
||||
/* we now need to copy the characters to the begin of line. As this overlaps,
|
||||
* we can not use strcpy(). -- rgerhards, 2008-03-20
|
||||
* TODO: review the code at whole - this is highly suspect (but will go away
|
||||
* once we do the rest of RainerScript).
|
||||
*/
|
||||
for( i = 0 ; p[i] != '\0' ; ++i) {
|
||||
cline[i] = p[i];
|
||||
}
|
||||
cline[i] = '\0';
|
||||
|
||||
for (p = (uchar*) strchr((char*)cline, '\0'); isspace((int) *--p);)
|
||||
/*EMPTY*/;
|
||||
if (*p == '\\') {
|
||||
if ((p - cbuf) > CFGLNSIZ - 30) {
|
||||
/* Oops the buffer is full - what now? */
|
||||
cline = cbuf;
|
||||
} else {
|
||||
*p = 0;
|
||||
cline = p;
|
||||
continue;
|
||||
}
|
||||
} else
|
||||
cline = cbuf;
|
||||
*++p = '\0'; /* TODO: check this */
|
||||
|
||||
/* we now have the complete line, and are positioned at the first non-whitespace
|
||||
* character. So let's process it
|
||||
*/
|
||||
if(cfline(conf, cbuf, &pCurrRule) != RS_RET_OK) {
|
||||
/* we log a message, but otherwise ignore the error. After all, the next
|
||||
* line can be correct. -- rgerhards, 2007-08-02
|
||||
*/
|
||||
uchar szErrLoc[MAXFNAME + 64];
|
||||
dbgprintf("config line NOT successfully processed\n");
|
||||
snprintf((char*)szErrLoc, sizeof(szErrLoc) / sizeof(uchar),
|
||||
"%s, line %d", pConfFile, iLnNbr);
|
||||
errmsg.LogError(0, NO_ERRCODE, "the last error occured in %s:\"%s\"", (char*)szErrLoc, (char*)pszOrgLine);
|
||||
bHadAnError = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* we probably have one selector left to be added - so let's do that now */
|
||||
if(pCurrRule != NULL) {
|
||||
CHKiRet(ruleset.AddRule(conf, rule.GetAssRuleset(pCurrRule), &pCurrRule));
|
||||
}
|
||||
|
||||
/* close the configuration file */
|
||||
fclose(cf);
|
||||
|
||||
finalize_it:
|
||||
if(iRet != RS_RET_OK) {
|
||||
char errStr[1024];
|
||||
if(pCurrRule != NULL)
|
||||
rule.Destruct(&pCurrRule);
|
||||
|
||||
rs_strerror_r(errno, errStr, sizeof(errStr));
|
||||
dbgprintf("error %d processing config file '%s'; os error (if any): %s\n",
|
||||
iRet, pConfFile, errStr);
|
||||
}
|
||||
|
||||
free(pszOrgLine);
|
||||
|
||||
if(bHadAnError && (iRet == RS_RET_OK)) { /* a bit dirty, enhance in future releases */
|
||||
iRet = RS_RET_NONFATAL_CONFIG_ERR;
|
||||
}
|
||||
RETiRet;
|
||||
}
|
||||
|
||||
|
||||
/* Helper to cfline() and its helpers. Parses a template name
|
||||
* from an "action" line. Must be called with the Line pointer
|
||||
* pointing to the first character after the semicolon.
|
||||
@ -1266,9 +1011,7 @@ CODESTARTobjQueryInterface(conf)
|
||||
pIf->doNameLine = doNameLine;
|
||||
pIf->cfsysline = cfsysline;
|
||||
pIf->doModLoad = doModLoad;
|
||||
pIf->doIncludeLine = doIncludeLine;
|
||||
pIf->cfline = cfline;
|
||||
pIf->processConfFile = processConfFile;
|
||||
pIf->GetNbrActActions = GetNbrActActions;
|
||||
|
||||
finalize_it:
|
||||
|
||||
@ -37,9 +37,7 @@ BEGINinterface(conf) /* name must also be changed in ENDinterface macro! */
|
||||
rsRetVal (*doNameLine)(uchar **pp, void* pVal);
|
||||
rsRetVal (*cfsysline)(uchar *p);
|
||||
rsRetVal (*doModLoad)(uchar **pp, __attribute__((unused)) void* pVal);
|
||||
rsRetVal (*doIncludeLine)(rsconf_t *conf, uchar **pp, __attribute__((unused)) void* pVal);
|
||||
rsRetVal (*cfline)(rsconf_t *conf, uchar *line, rule_t **pfCurr);
|
||||
rsRetVal (*processConfFile)(rsconf_t *conf, uchar *pConfFile);
|
||||
rsRetVal (*GetNbrActActions)(rsconf_t *conf, int *);
|
||||
/* version 4 -- 2010-07-23 rgerhards */
|
||||
/* "just" added global variables
|
||||
|
||||
@ -385,7 +385,7 @@ void cnfDoRule(struct cnfrule *cnfrule)
|
||||
break;
|
||||
case CNFFILT_SCRIPT:
|
||||
pRule->f_filter_type = FILTER_EXPR;
|
||||
pRule->f_filterData.f_expr = cnfrule->filt.expr;
|
||||
pRule->f_filterData.expr = cnfrule->filt.expr;
|
||||
break;
|
||||
}
|
||||
/* we now check if there are some global (BSD-style) filter conditions
|
||||
@ -790,19 +790,6 @@ static rsRetVal setActionResumeInterval(void __attribute__((unused)) *pVal, int
|
||||
}
|
||||
|
||||
|
||||
/* this method is needed to shuffle the current conf object down to the
|
||||
* IncludeConfig handler.
|
||||
*/
|
||||
static rsRetVal
|
||||
doIncludeLine(void *pVal, uchar *pNewVal)
|
||||
{
|
||||
DEFiRet;
|
||||
iRet = conf.doIncludeLine(ourConf, pVal, pNewVal);
|
||||
free(pNewVal);
|
||||
RETiRet;
|
||||
}
|
||||
|
||||
|
||||
/* set the maximum message size */
|
||||
static rsRetVal setMaxMsgSize(void __attribute__((unused)) *pVal, long iNewVal)
|
||||
{
|
||||
@ -1081,8 +1068,6 @@ initLegacyConf(void)
|
||||
setActionResumeInterval, NULL, NULL, eConfObjGlobal));
|
||||
CHKiRet(regCfSysLineHdlr((uchar *)"modload", 0, eCmdHdlrCustomHandler,
|
||||
conf.doModLoad, NULL, NULL, eConfObjGlobal));
|
||||
CHKiRet(regCfSysLineHdlr((uchar *)"includeconfig", 0, eCmdHdlrCustomHandler,
|
||||
doIncludeLine, NULL, NULL, eConfObjGlobal));
|
||||
CHKiRet(regCfSysLineHdlr((uchar *)"maxmessagesize", 0, eCmdHdlrSize,
|
||||
setMaxMsgSize, NULL, NULL, eConfObjGlobal));
|
||||
CHKiRet(regCfSysLineHdlr((uchar *)"defaultruleset", 0, eCmdHdlrGetWord,
|
||||
@ -1236,6 +1221,7 @@ load(rsconf_t **cnf, uchar *confFile)
|
||||
int bHadConfigErr = 0;
|
||||
char cbuf[BUFSIZ];
|
||||
int r;
|
||||
char *emergConf;
|
||||
DEFiRet;
|
||||
|
||||
CHKiRet(rsconfConstruct(&loadConf));
|
||||
@ -1246,11 +1232,12 @@ ourConf = loadConf; // TODO: remove, once ourConf is gone!
|
||||
|
||||
/* open the configuration file */
|
||||
r = cnfSetLexFile((char*)confFile);
|
||||
r = yyparse();
|
||||
//localRet = conf.processConfFile(loadConf, confFile);
|
||||
CHKiRet(conf.GetNbrActActions(loadConf, &iNbrActions));
|
||||
if(r == 0) {
|
||||
r = yyparse();
|
||||
conf.GetNbrActActions(loadConf, &iNbrActions);
|
||||
}
|
||||
|
||||
if(localRet != RS_RET_OK && localRet != RS_RET_NONFATAL_CONFIG_ERR) {
|
||||
if(r == 1) {
|
||||
errmsg.LogError(0, localRet, "CONFIG ERROR: could not interpret master config file '%s'.", confFile);
|
||||
bHadConfigErr = 1;
|
||||
} else if(iNbrActions == 0) {
|
||||
@ -1259,8 +1246,7 @@ ourConf = loadConf; // TODO: remove, once ourConf is gone!
|
||||
bHadConfigErr = 1;
|
||||
}
|
||||
|
||||
if((localRet != RS_RET_OK && localRet != RS_RET_NONFATAL_CONFIG_ERR) || iNbrActions == 0) {
|
||||
|
||||
if(r == 1 || iNbrActions == 0) {
|
||||
/* rgerhards: this code is executed to set defaults when the
|
||||
* config file could not be opened. We might think about
|
||||
* abandoning the run in this case - but this, too, is not
|
||||
@ -1268,23 +1254,17 @@ ourConf = loadConf; // TODO: remove, once ourConf is gone!
|
||||
* We ignore any errors while doing this - we would be lost anyhow...
|
||||
*/
|
||||
errmsg.LogError(0, NO_ERRCODE, "EMERGENCY CONFIGURATION ACTIVATED - fix rsyslog config file!");
|
||||
|
||||
/* note: we previously used _POSIY_TTY_NAME_MAX+1, but this turned out to be
|
||||
* too low on linux... :-S -- rgerhards, 2008-07-28
|
||||
*/
|
||||
char szTTYNameBuf[128];
|
||||
rule_t *pRule = NULL; /* initialization to NULL is *vitally* important! */
|
||||
conf.cfline(loadConf, UCHAR_CONSTANT("*.ERR\t" _PATH_CONSOLE), &pRule);
|
||||
conf.cfline(loadConf, UCHAR_CONSTANT("syslog.*\t" _PATH_CONSOLE), &pRule);
|
||||
conf.cfline(loadConf, UCHAR_CONSTANT("*.PANIC\t*"), &pRule);
|
||||
conf.cfline(loadConf, UCHAR_CONSTANT("syslog.*\troot"), &pRule);
|
||||
if(ttyname_r(0, szTTYNameBuf, sizeof(szTTYNameBuf)) == 0) {
|
||||
snprintf(cbuf,sizeof(cbuf), "*.*\t%s", szTTYNameBuf);
|
||||
conf.cfline(loadConf, (uchar*)cbuf, &pRule);
|
||||
} else {
|
||||
DBGPRINTF("error %d obtaining controlling terminal, not using that emergency rule\n", errno);
|
||||
emergConf =
|
||||
"*.err " _PATH_CONSOLE "\n"
|
||||
"syslog.*" _PATH_CONSOLE "\n"
|
||||
"*.panic :omusrmsg:*" "\n"
|
||||
"syslog.* :omusrmsg:root" "\n";
|
||||
cnfParseBuffer(emergConf, strlen(emergConf));
|
||||
r = yyparse();
|
||||
if(r != 0) {
|
||||
fprintf(stderr, "rsyslogd: could not even activate emergency conf - terminating\n");
|
||||
exit(1);
|
||||
}
|
||||
ruleset.AddRule(loadConf, ruleset.GetCurrent(loadConf), &pRule);
|
||||
}
|
||||
|
||||
CHKiRet(validateConf());
|
||||
|
||||
@ -183,15 +183,6 @@ shouldProcessThisMessage(rule_t *pRule, msg_t *pMsg, sbool *bProcessMsg)
|
||||
else
|
||||
bRet = 1;
|
||||
} else if(pRule->f_filter_type == FILTER_EXPR) {
|
||||
#if 0
|
||||
CHKiRet(vm.Construct(&pVM));
|
||||
CHKiRet(vm.ConstructFinalize(pVM));
|
||||
CHKiRet(vm.SetMsg(pVM, pMsg));
|
||||
CHKiRet(vm.ExecProg(pVM, pRule->f_filterData.f_expr->pVmprg));
|
||||
CHKiRet(vm.PopBoolFromStack(pVM, &pResult));
|
||||
/* VM is destructed on function exit */
|
||||
bRet = (pResult->val.num) ? 1 : 0;
|
||||
#endif
|
||||
bRet = cnfexprEvalBool(pRule->f_filterData.expr, pMsg);
|
||||
dbgprintf("result of rainerscript filter evaluation: %d\n", bRet);
|
||||
} else {
|
||||
|
||||
@ -54,7 +54,6 @@ struct rule_s {
|
||||
es_str_t *propName; /* name of property for CEE-based filters */
|
||||
} prop;
|
||||
struct cnfexpr *expr; /* expression object */
|
||||
expr_t *f_expr; /* expression object */
|
||||
} f_filterData;
|
||||
|
||||
ruleset_t *pRuleset; /* associated ruleset */
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
if ENABLE_TESTBENCH
|
||||
# TODO: reenable TESTRUNS = rt_init rscript
|
||||
check_PROGRAMS = $(TESTRUNS) ourtail nettester tcpflood chkseq msleep randomgen diagtalker uxsockrcvr syslog_caller syslog_inject inputfilegen
|
||||
TESTS = $(TESTRUNS) cfg.sh
|
||||
TESTS = $(TESTRUNS)
|
||||
#TESTS = $(TESTRUNS) cfg.sh
|
||||
|
||||
if ENABLE_IMDIAG
|
||||
TESTS += \
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user