summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--action.c32
-rw-r--r--action.h2
-rw-r--r--doc/features.html3
-rw-r--r--doc/rsyslog_conf_modules.html7
-rw-r--r--plugins/imklog/linux.c2
-rw-r--r--plugins/omstdout/omstdout.c80
-rw-r--r--runtime/cfsysline.c4
-rw-r--r--runtime/debug.c2
-rw-r--r--runtime/modules.c2
-rw-r--r--runtime/objomsr.c18
-rw-r--r--runtime/objomsr.h6
-rw-r--r--runtime/rsyslog.h5
-rw-r--r--runtime/stringbuf.c38
-rw-r--r--runtime/stringbuf.h3
-rw-r--r--template.c56
-rw-r--r--template.h1
-rw-r--r--tools/omfile.c12
-rw-r--r--tools/pidfile.c2
-rw-r--r--tools/syslogd.c8
-rw-r--r--tools/syslogd.h1
21 files changed, 259 insertions, 30 deletions
diff --git a/ChangeLog b/ChangeLog
index 42fda5b3..7f79271f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -34,6 +34,11 @@ Version 4.1.6 [DEVEL] (rgerhards), 2009-03-??
the full high availability features of rsyslog's engine
- bugfix: fixed some segaults on Solaris, where vsprintf() does not
check for NULL pointers
+- improved performance of regexp-based filters
+ Thanks to Arnaud Cornet for providing the idea and initial patch.
+- added a new way how output plugins may be passed parameters. This is
+ more effcient for some outputs. They new can receive fields not only
+ as a single string but rather in an array where each string is seperated.
---------------------------------------------------------------------------
Version 4.1.5 [DEVEL] (rgerhards), 2009-03-11
- bugfix: parser did not correctly parse fields in UDP-received messages
diff --git a/action.c b/action.c
index 08755c13..03073153 100644
--- a/action.c
+++ b/action.c
@@ -425,6 +425,7 @@ actionCallDoAction(action_t *pAction, msg_t *pMsg)
DEFiRet;
int iRetries;
int i;
+ int iArr;
int iSleepPeriod;
int bCallAction;
int iCancelStateSave;
@@ -439,7 +440,15 @@ actionCallDoAction(action_t *pAction, msg_t *pMsg)
/* here we must loop to process all requested strings */
for(i = 0 ; i < pAction->iNumTpls ; ++i) {
- CHKiRet(tplToString(pAction->ppTpl[i], pMsg, &(ppMsgs[i])));
+ switch(pAction->eParamPassing) {
+ case ACT_STRING_PASSING:
+ CHKiRet(tplToString(pAction->ppTpl[i], pMsg, &(ppMsgs[i])));
+ break;
+ case ACT_ARRAY_PASSING:
+ CHKiRet(tplToArray(pAction->ppTpl[i], pMsg, (uchar***) &(ppMsgs[i])));
+ break;
+ default:assert(0); /* software bug if this happens! */
+ }
}
iRetries = 0;
/* We now must guard the output module against execution by multiple threads. The
@@ -495,7 +504,19 @@ finalize_it:
/* cleanup */
for(i = 0 ; i < pAction->iNumTpls ; ++i) {
if(ppMsgs[i] != NULL) {
- d_free(ppMsgs[i]);
+ switch(pAction->eParamPassing) {
+ case ACT_ARRAY_PASSING:
+ iArr = 0;
+ while(((char **)ppMsgs[i])[iArr] != NULL)
+ d_free(((char **)ppMsgs[i])[iArr++]);
+ d_free(ppMsgs[i]);
+ break;
+ case ACT_STRING_PASSING:
+ d_free(ppMsgs[i]);
+ break;
+ default:
+ assert(0);
+ }
}
}
d_free(ppMsgs);
@@ -905,6 +926,13 @@ addAction(action_t **ppAction, modInfo_t *pMod, void *pModData, omodStringReques
ABORT_FINALIZE(RS_RET_RQD_TPLOPT_MISSING);
}
+ /* set parameter-passing mode */
+ if(iTplOpts & OMSR_TPL_AS_ARRAY) {
+ pAction->eParamPassing = ACT_ARRAY_PASSING;
+ } else {
+ pAction->eParamPassing = ACT_STRING_PASSING;
+ }
+
dbgprintf("template: '%s' assigned\n", pTplName);
}
diff --git a/action.h b/action.h
index dc9bbd74..f2706af6 100644
--- a/action.h
+++ b/action.h
@@ -61,6 +61,8 @@ struct action_s {
short f_ReduceRepeated;/* reduce repeated lines 0 - no, 1 - yes */
int f_prevcount; /* repetition cnt of prevline */
int f_repeatcount; /* number of "repeated" msgs */
+ enum { ACT_STRING_PASSING = 0, ACT_ARRAY_PASSING = 1 }
+ eParamPassing; /* mode of parameter passing to action */
int iNumTpls; /* number of array entries for template element below */
struct template **ppTpl;/* array of template to use - strings must be passed to doAction
* in this order. */
diff --git a/doc/features.html b/doc/features.html
index 501f3304..17a995bf 100644
--- a/doc/features.html
+++ b/doc/features.html
@@ -95,6 +95,9 @@ via custom plugins</li>
<li> an easy-to-write to plugin interface</li>
<li> ability to send SNMP trap messages</li>
<li> ability to filter out messages based on sequence of arrival</li>
+<li>support for comma-seperated-values (CSV) output generation
+(via the "csv" property replace option). The
+CSV format supported is that from RFC 4180.</li>
<li>support for arbitrary complex boolean, string and
arithmetic expressions in message filters</li>
</ul>
diff --git a/doc/rsyslog_conf_modules.html b/doc/rsyslog_conf_modules.html
index 890a55c8..a281d9e7 100644
--- a/doc/rsyslog_conf_modules.html
+++ b/doc/rsyslog_conf_modules.html
@@ -8,10 +8,9 @@
number of modules. Here is the entry point to their documentation and
what they do (list is currently not complete)</p>
<ul>
-<li><a href="omsnmp.html">omsnmp</a> - SNMP
-trap output module</li>
-<li><a href="omrelp.html">omrelp</a> - RELP
-output module</li>
+<li><a href="omsnmp.html">omsnmp</a> - SNMP trap output module</li>
+<li><a href="omstdout.html">omtdout</a> - stdout output module (mainly a test tool)</li>
+<li><a href="omrelp.html">omrelp</a> - RELP output module</li>
<li>omgssapi - output module for GSS-enabled syslog</li>
<li><a href="ommysql.html">ommysql</a> - output module for MySQL</li>
<li>ompgsql - output module for PostgreSQL</li>
diff --git a/plugins/imklog/linux.c b/plugins/imklog/linux.c
index 198b7c0e..0dd4320d 100644
--- a/plugins/imklog/linux.c
+++ b/plugins/imklog/linux.c
@@ -144,7 +144,7 @@ static enum LOGSRC GetKernelLogSrc(void)
return(kernel);
}
- if ( (kmsg = open(_PATH_KLOG, O_RDONLY)) < 0 )
+ if ( (kmsg = open(_PATH_KLOG, O_RDONLY|O_CLOEXEC)) < 0 )
{
imklogLogIntMsg(LOG_ERR, "imklog: Cannot open proc file system, %d.\n", errno);
ksyslog(7, NULL, 0); /* TODO: check this, implement more */
diff --git a/plugins/omstdout/omstdout.c b/plugins/omstdout/omstdout.c
index 6e227ba9..e491005c 100644
--- a/plugins/omstdout/omstdout.c
+++ b/plugins/omstdout/omstdout.c
@@ -49,7 +49,12 @@ MODULE_TYPE_OUTPUT
*/
DEF_OMOD_STATIC_DATA
+/* config variables */
+static int bUseArrayInterface; /* shall action use array instead of string template interface? */
+
+
typedef struct _instanceData {
+ int bUseArrayInterface; /* uses action use array instead of string template interface? */
} instanceData;
BEGINcreateInstance
@@ -79,12 +84,46 @@ CODESTARTtryResume
ENDtryResume
BEGINdoAction
+ char **szParams;
+ char *toWrite;
+ int iParamVal;
+ int iParam;
+ int iBuf;
+ char szBuf[65564];
CODESTARTdoAction
- write(1, (char*)ppString[0], strlen((char*)ppString[0]));
+ if(pData->bUseArrayInterface) {
+ /* if we use array passing, we need to put together a string
+ * ourselves. At this point, please keep in mind that omstdout is
+ * primarily a testing aid. Other modules may do different processing
+ * if they would like to support downlevel versions which do not support
+ * array-passing, but also use that interface on cores who do...
+ * So this code here is also more or less an example of how to do that.
+ * rgerhards, 2009-04-03
+ */
+ szParams = (char**) (ppString[0]);
+ /* In array-passing mode, ppString[] contains a NULL-terminated array
+ * of char *pointers.
+ */
+ iParam = 0;
+ iBuf = 0;
+ while(szParams[iParam] != NULL) {
+ iParamVal = 0;
+ while(szParams[iParam][iParamVal] != '\0' && iBuf < sizeof(szBuf)) {
+ szBuf[iBuf++] = szParams[iParam][iParamVal++];
+ }
+ ++iParam;
+ }
+ szBuf[iBuf] = '\0';
+ toWrite = szBuf;
+ } else {
+ toWrite = (char*) ppString[0];
+ }
+ write(1, toWrite, strlen(toWrite)); /* 1 is stdout! */
ENDdoAction
BEGINparseSelectorAct
+ int iTplOpts;
CODESTARTparseSelectorAct
CODE_STD_STRING_REQUESTparseSelectorAct(1)
/* first check if this config line is actually for us */
@@ -99,7 +138,9 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1)
/* check if a non-standard template is to be applied */
if(*(p-1) == ';')
--p;
- CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, 0, (uchar*) "RSYSLOG_FileFormat"));
+ iTplOpts = (bUseArrayInterface == 0) ? 0 : OMSR_TPL_AS_ARRAY;
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, iTplOpts, (uchar*) "RSYSLOG_FileFormat"));
+ pData->bUseArrayInterface = bUseArrayInterface;
CODE_STD_FINALIZERparseSelectorAct
ENDparseSelectorAct
@@ -115,10 +156,45 @@ CODEqueryEtryPt_STD_OMOD_QUERIES
ENDqueryEtryPt
+
+/* Reset config variables for this module to default values.
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ DEFiRet;
+ bUseArrayInterface = 0;
+ RETiRet;
+}
+
+
BEGINmodInit()
+ rsRetVal localRet;
+ rsRetVal (*pomsrGetSupportedTplOpts)(unsigned long *pOpts);
+ unsigned long opts;
+ int bArrayPassingSupported; /* does core support template passing as an array? */
CODESTARTmodInit
*ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
CODEmodInit_QueryRegCFSLineHdlr
+ /* check if the rsyslog core supports parameter passing code */
+ bArrayPassingSupported = 0;
+ localRet = pHostQueryEtryPt((uchar*)"OMSRgetSupportedTplOpts", &pomsrGetSupportedTplOpts);
+ if(localRet == RS_RET_OK) {
+ /* found entry point, so let's see if core supports array passing */
+ CHKiRet((*pomsrGetSupportedTplOpts)(&opts));
+ if(opts & OMSR_TPL_AS_ARRAY)
+ bArrayPassingSupported = 1;
+ } else if(localRet != RS_RET_ENTRY_POINT_NOT_FOUND) {
+ ABORT_FINALIZE(localRet); /* Something else went wrong, what is not acceptable */
+ }
+ DBGPRINTF("omstdout: array-passing is %ssupported by rsyslog core.\n", bArrayPassingSupported ? "" : "not ");
+
+ if(bArrayPassingSupported) {
+ /* enable config comand only if core supports it */
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionomstdoutarrayinterface", 0, eCmdHdlrBinary, NULL,
+ &bUseArrayInterface, STD_LOADABLE_MODULE_ID));
+ }
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
ENDmodInit
/* vi:set ai:
diff --git a/runtime/cfsysline.c b/runtime/cfsysline.c
index c4490b48..e1e4a6a4 100644
--- a/runtime/cfsysline.c
+++ b/runtime/cfsysline.c
@@ -364,7 +364,7 @@ static rsRetVal doGetGID(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *p
/* we set value via a set function */
CHKiRet(pSetHdlr(pVal, pgBuf->gr_gid));
}
- dbgprintf("gid %d obtained for group '%s'\n", pgBuf->gr_gid, szName);
+ dbgprintf("gid %d obtained for group '%s'\n", (int) pgBuf->gr_gid, szName);
}
skipWhiteSpace(pp); /* skip over any whitespace */
@@ -406,7 +406,7 @@ static rsRetVal doGetUID(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *p
/* we set value via a set function */
CHKiRet(pSetHdlr(pVal, ppwBuf->pw_uid));
}
- dbgprintf("uid %d obtained for user '%s'\n", ppwBuf->pw_uid, szName);
+ dbgprintf("uid %d obtained for user '%s'\n", (int) ppwBuf->pw_uid, szName);
}
skipWhiteSpace(pp); /* skip over any whitespace */
diff --git a/runtime/debug.c b/runtime/debug.c
index 96004e47..4ee90226 100644
--- a/runtime/debug.c
+++ b/runtime/debug.c
@@ -1343,7 +1343,7 @@ rsRetVal dbgClassInit(void)
if(pszAltDbgFileName != NULL) {
/* we have a secondary file, so let's open it) */
- if((altdbg = open(pszAltDbgFileName, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, S_IRUSR|S_IWUSR)) == -1) {
+ if((altdbg = open(pszAltDbgFileName, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, S_IRUSR|S_IWUSR)) == -1) {
fprintf(stderr, "alternate debug file could not be opened, ignoring. Error: %s\n", strerror(errno));
}
}
diff --git a/runtime/modules.c b/runtime/modules.c
index cef4eac6..9fdb48e7 100644
--- a/runtime/modules.c
+++ b/runtime/modules.c
@@ -225,6 +225,8 @@ static rsRetVal queryHostEtryPt(uchar *name, rsRetVal (**pEtryPoint)())
*pEtryPoint = regCfSysLineHdlr;
} else if(!strcmp((char*) name, "objGetObjInterface")) {
*pEtryPoint = objGetObjInterface;
+ } else if(!strcmp((char*) name, "OMSRgetSupportedTplOpts")) {
+ *pEtryPoint = OMSRgetSupportedTplOpts;
} else {
*pEtryPoint = NULL; /* to be on the safe side */
ABORT_FINALIZE(RS_RET_ENTRY_POINT_NOT_FOUND);
diff --git a/runtime/objomsr.c b/runtime/objomsr.c
index 21d284f3..8dddc4b8 100644
--- a/runtime/objomsr.c
+++ b/runtime/objomsr.c
@@ -141,5 +141,23 @@ int OMSRgetEntry(omodStringRequest_t *pThis, int iEntry, uchar **ppTplName, int
return RS_RET_OK;
}
+
+
+/* return the full set of template options that are supported by this version of
+ * OMSR. They are returned in an unsigned long value. The caller can mask that
+ * value to check on the option he is interested in.
+ * Note that this interface was added in 4.1.6, so a plugin must obtain a pointer
+ * to this interface via queryHostEtryPt().
+ * rgerhards, 2009-04-03
+ */
+rsRetVal
+OMSRgetSupportedTplOpts(unsigned long *pOpts)
+{
+ DEFiRet;
+ assert(pOpts != NULL);
+ *pOpts = OMSR_RQD_TPL_OPT_SQL | OMSR_TPL_AS_ARRAY;
+ RETiRet;
+}
+
/* vim:set ai:
*/
diff --git a/runtime/objomsr.h b/runtime/objomsr.h
index 2255e4f3..75ad0fb8 100644
--- a/runtime/objomsr.h
+++ b/runtime/objomsr.h
@@ -1,6 +1,6 @@
/* Definition of the omsr (omodStringRequest) object.
*
- * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2007, 2009 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
@@ -27,7 +27,8 @@
/* define flags for required template options */
#define OMSR_NO_RQD_TPL_OPTS 0
#define OMSR_RQD_TPL_OPT_SQL 1
-/* next option is 2, 4, 8, ... */
+#define OMSR_TPL_AS_ARRAY 2 /* introduced in 4.1.6, 2009-04-03 */
+/* next option is 4, 8, 16, ... */
struct omodStringRequest_s { /* strings requested by output module for doAction() */
int iNumEntries; /* number of array entries for data elements below */
@@ -40,6 +41,7 @@ typedef struct omodStringRequest_s omodStringRequest_t;
rsRetVal OMSRdestruct(omodStringRequest_t *pThis);
rsRetVal OMSRconstruct(omodStringRequest_t **ppThis, int iNumEntries);
rsRetVal OMSRsetEntry(omodStringRequest_t *pThis, int iEntry, uchar *pTplName, int iTplOpts);
+rsRetVal OMSRgetSupportedTplOpts(unsigned long *pOpts);
int OMSRgetEntryCount(omodStringRequest_t *pThis);
int OMSRgetEntry(omodStringRequest_t *pThis, int iEntry, uchar **ppTplName, int *piTplOpts);
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index 899f5e13..032d8c04 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -341,6 +341,11 @@ typedef enum rsObjectID rsObjID;
# define __attribute__(x) /*NOTHING*/
#endif
+#ifndef O_CLOEXEC
+/* of course, this limits the functionality... */
+# define O_CLOEXEC 0
+#endif
+
/* The following prototype is convenient, even though it may not be the 100% correct place.. -- rgerhards 2008-01-07 */
void dbgprintf(char *, ...) __attribute__((format(printf, 1, 2)));
diff --git a/runtime/stringbuf.c b/runtime/stringbuf.c
index a5dc625a..35ec44c6 100644
--- a/runtime/stringbuf.c
+++ b/runtime/stringbuf.c
@@ -703,17 +703,26 @@ int rsCStrCaseInsensitveStartsWithSzStr(cstr_t *pCS1, uchar *psz, size_t iLenSz)
* never is a \0 *inside* a property string.
* Note that the function returns -1 if regexp functionality is not available.
* rgerhards: 2009-03-04: ERE support added, via parameter iType: 0 - BRE, 1 - ERE
+ * Arnaud Cornet/rgerhards: 2009-04-02: performance improvement by caching compiled regex
+ * If a caller does not need the cached version, it must still provide memory for it
+ * and must call rsCStrRegexDestruct() afterwards.
*/
-rsRetVal rsCStrSzStrMatchRegex(cstr_t *pCS1, uchar *psz, int iType)
+rsRetVal rsCStrSzStrMatchRegex(cstr_t *pCS1, uchar *psz, int iType, void *rc)
{
- regex_t preq;
+ regex_t **cache = (regex_t**) rc;
int ret;
DEFiRet;
+ assert(pCS1 != NULL);
+ assert(psz != NULL);
+ assert(cache != NULL);
+
if(objUse(regexp, LM_REGEXP_FILENAME) == RS_RET_OK) {
- regexp.regcomp(&preq, (char*) rsCStrGetSzStr(pCS1), (iType == 1 ? REG_EXTENDED : 0) | REG_NOSUB);
- ret = regexp.regexec(&preq, (char*) psz, 0, NULL, 0);
- regexp.regfree(&preq);
+ if (*cache == NULL) {
+ *cache = calloc(sizeof(regex_t), 1);
+ regexp.regcomp(*cache, (char*) rsCStrGetSzStr(pCS1), (iType == 1 ? REG_EXTENDED : 0) | REG_NOSUB);
+ }
+ ret = regexp.regexec(*cache, (char*) psz, 0, NULL, 0);
if(ret != 0)
ABORT_FINALIZE(RS_RET_NOT_FOUND);
} else {
@@ -725,6 +734,25 @@ finalize_it:
}
+/* free a cached compiled regex
+ * Caller must provide a pointer to a buffer that was created by
+ * rsCStrSzStrMatchRegexCache()
+ */
+void rsCStrRegexDestruct(void *rc)
+{
+ regex_t **cache = rc;
+
+ assert(cache != NULL);
+ assert(*cache != NULL);
+
+ if(objUse(regexp, LM_REGEXP_FILENAME) == RS_RET_OK) {
+ regexp.regfree(*cache);
+ free(*cache);
+ *cache = NULL;
+ }
+}
+
+
/* compare a rsCStr object with a classical sz string. This function
* is almost identical to rsCStrZsStrCmp(), but it also takes an offset
* to the CStr object from where the comparison is to start.
diff --git a/runtime/stringbuf.h b/runtime/stringbuf.h
index f3e08439..684133bb 100644
--- a/runtime/stringbuf.h
+++ b/runtime/stringbuf.h
@@ -136,7 +136,8 @@ int rsCStrCaseInsensitiveLocateInSzStr(cstr_t *pThis, uchar *sz);
int rsCStrStartsWithSzStr(cstr_t *pCS1, uchar *psz, size_t iLenSz);
int rsCStrCaseInsensitveStartsWithSzStr(cstr_t *pCS1, uchar *psz, size_t iLenSz);
int rsCStrSzStrStartsWithCStr(cstr_t *pCS1, uchar *psz, size_t iLenSz);
-rsRetVal rsCStrSzStrMatchRegex(cstr_t *pCS1, uchar *psz, int iType);
+rsRetVal rsCStrSzStrMatchRegex(cstr_t *pCS1, uchar *psz, int iType, void *cache);
+void rsCStrRegexDestruct(void *rc);
rsRetVal rsCStrConvertToNumber(cstr_t *pStr, number_t *pNumber);
rsRetVal rsCStrConvertToBool(cstr_t *pStr, number_t *pBool);
rsRetVal rsCStrAppendCStr(cstr_t *pThis, cstr_t *pstrAppend);
diff --git a/template.c b/template.c
index 4f507ff6..4a12aa3b 100644
--- a/template.c
+++ b/template.c
@@ -47,6 +47,8 @@ static struct template *tplRoot = NULL; /* the root of the template list */
static struct template *tplLast = NULL; /* points to the last element of the template list */
static struct template *tplLastStatic = NULL; /* last static element of the template list */
+
+
/* This functions converts a template into a string. It should
* actually be in template.c, but this requires larger re-structuring
* of the code (because all the property-access functions are static
@@ -140,6 +142,60 @@ finalize_it:
RETiRet;
}
+
+/* This functions converts a template into an array of strings.
+ * For further general details, see the very similar funtion
+ * tpltoString().
+ * Instead of a string, an array of string pointers is returned by
+ * thus function. The caller is repsonsible for destroying that array as
+ * well as all of its elements. The array is of fixed size. It's end
+ * is indicated by a NULL pointer.
+ * rgerhards, 2009-04-03
+ */
+rsRetVal tplToArray(struct template *pTpl, msg_t *pMsg, uchar*** ppArr)
+{
+ DEFiRet;
+ struct templateEntry *pTpe;
+ uchar **pArr;
+ int iArr;
+ unsigned short bMustBeFreed;
+ uchar *pVal;
+
+ assert(pTpl != NULL);
+ assert(pMsg != NULL);
+ assert(ppArr != NULL);
+
+ /* loop through the template. We obtain one value, create a
+ * private copy (if necessary), add it to the string array
+ * and then on to the next until we have processed everything.
+ */
+
+ CHKmalloc(pArr = calloc(pTpl->tpenElements + 1, sizeof(uchar*)));
+ iArr = 0;
+
+ pTpe = pTpl->pEntryRoot;
+ while(pTpe != NULL) {
+ if(pTpe->eEntryType == CONSTANT) {
+ CHKmalloc(pArr[iArr] = (uchar*)strdup((char*) pTpe->data.constant.pConstant));
+ } else if(pTpe->eEntryType == FIELD) {
+ pVal = (uchar*) MsgGetProp(pMsg, pTpe, NULL, &bMustBeFreed);
+ if(bMustBeFreed) { /* if it must be freed, it is our own private copy... */
+ pArr[iArr] = pVal; /* ... so we can use it! */
+ } else {
+ CHKmalloc(pArr[iArr] = (uchar*)strdup((char*) pVal));
+ }
+ }
+ iArr++;
+ pTpe = pTpe->pNext;
+ }
+
+finalize_it:
+ *ppArr = (iRet == RS_RET_OK) ? pArr : NULL;
+
+ RETiRet;
+}
+
+
/* Helper to doSQLEscape. This is called if doSQLEscape
* runs out of memory allocating the escaped string.
* Then we are in trouble. We can
diff --git a/template.h b/template.h
index 6ca8dc6c..9d794f66 100644
--- a/template.h
+++ b/template.h
@@ -126,6 +126,7 @@ void tplLastStaticInit(struct template *tpl);
* BEFORE msg.h, even if your code file does not actually need it.
* rgerhards, 2007-08-06
*/
+rsRetVal tplToArray(struct template *pTpl, msg_t *pMsg, uchar*** ppArr);
rsRetVal tplToString(struct template *pTpl, msg_t *pMsg, uchar** ppSz);
rsRetVal doSQLEscape(uchar **pp, size_t *pLen, unsigned short *pbMustBeFreed, int escapeMode);
diff --git a/tools/omfile.c b/tools/omfile.c
index 5141b4da..36f160d1 100644
--- a/tools/omfile.c
+++ b/tools/omfile.c
@@ -301,7 +301,7 @@ int resolveFileSizeLimit(instanceData *pData)
free(pCmd);
- pData->fd = open((char*) pData->f_fname, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY,
+ pData->fd = open((char*) pData->f_fname, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY|O_CLOEXEC,
pData->fCreateMode);
actualFileSize = lseek(pData->fd, 0, SEEK_END);
@@ -394,13 +394,13 @@ prepareFile(instanceData *pData, uchar *newFileName)
{
DEFiRet;
if(pData->fileType == eTypePIPE) {
- pData->fd = open((char*) pData->f_fname, O_RDWR|O_NONBLOCK);
+ pData->fd = open((char*) pData->f_fname, O_RDWR|O_NONBLOCK|O_CLOEXEC);
FINALIZE; /* we are done in this case */
}
if(access((char*)newFileName, F_OK) == 0) {
/* file already exists */
- pData->fd = open((char*) newFileName, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY,
+ pData->fd = open((char*) newFileName, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY|O_CLOEXEC,
pData->fCreateMode);
} else {
pData->fd = -1;
@@ -419,7 +419,7 @@ prepareFile(instanceData *pData, uchar *newFileName)
/* no matter if we needed to create directories or not, we now try to create
* the file. -- rgerhards, 2008-12-18 (based on patch from William Tisater)
*/
- pData->fd = open((char*) newFileName, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY,
+ pData->fd = open((char*) newFileName, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY|O_CLOEXEC,
pData->fCreateMode);
if(pData->fd != -1) {
/* check and set uid/gid */
@@ -653,7 +653,7 @@ again:
&& e == EBADF
#endif
) {
- pData->fd = open((char*) pData->f_fname, O_WRONLY|O_APPEND|O_NOCTTY);
+ pData->fd = open((char*) pData->f_fname, O_WRONLY|O_APPEND|O_NOCTTY|O_CLOEXEC);
if (pData->fd < 0) {
iRet = RS_RET_SUSPENDED;
errmsg.LogError(0, NO_ERRCODE, "%s", pData->f_fname);
@@ -742,7 +742,7 @@ CODESTARTparseSelectorAct
pData->bDynamicName = 0;
pData->fCreateMode = fCreateMode; /* preserve current setting */
pData->fDirCreateMode = fDirCreateMode; /* preserve current setting */
- pData->fd = open((char*) pData->f_fname, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY,
+ pData->fd = open((char*) pData->f_fname, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY|O_CLOEXEC,
pData->fCreateMode);
}
break;
diff --git a/tools/pidfile.c b/tools/pidfile.c
index 2be13da6..e7744513 100644
--- a/tools/pidfile.c
+++ b/tools/pidfile.c
@@ -97,7 +97,7 @@ int write_pid (char *pidfile)
int fd;
int pid;
- if ( ((fd = open(pidfile, O_RDWR|O_CREAT, 0644)) == -1)
+ if ( ((fd = open(pidfile, O_RDWR|O_CREAT|O_CLOEXEC, 0644)) == -1)
|| ((f = fdopen(fd, "r+")) == NULL) ) {
fprintf(stderr, "Can't open or create %s.\n", pidfile);
return 0;
diff --git a/tools/syslogd.c b/tools/syslogd.c
index c72160fb..b23c12a7 100644
--- a/tools/syslogd.c
+++ b/tools/syslogd.c
@@ -429,6 +429,8 @@ selectorDestruct(void *pVal)
rsCStrDestruct(&pThis->f_filterData.prop.pCSPropName);
if(pThis->f_filterData.prop.pCSCompValue != NULL)
rsCStrDestruct(&pThis->f_filterData.prop.pCSCompValue);
+ if(pThis->f_filterData.prop.regex_cache != NULL)
+ rsCStrRegexDestruct(&pThis->f_filterData.prop.regex_cache);
} else if(pThis->f_filter_type == FILTER_EXPR) {
if(pThis->f_filterData.f_expr != NULL)
expr.Destruct(&pThis->f_filterData.f_expr);
@@ -549,7 +551,7 @@ void untty(void)
int i;
if ( !Debug ) {
- i = open(_PATH_TTY, O_RDWR);
+ i = open(_PATH_TTY, O_RDWR|O_CLOEXEC);
if (i >= 0) {
# if !defined(__hpux)
(void) ioctl(i, (int) TIOCNOTTY, (char *)0);
@@ -1076,12 +1078,12 @@ static rsRetVal shouldProcessThisMessage(selector_t *f, msg_t *pMsg, int *bProce
break;
case FIOP_REGEX:
if(rsCStrSzStrMatchRegex(f->f_filterData.prop.pCSCompValue,
- (unsigned char*) pszPropVal, 0) == RS_RET_OK)
+ (unsigned char*) pszPropVal, 0, &f->f_filterData.prop.regex_cache) == RS_RET_OK)
bRet = 1;
break;
case FIOP_EREREGEX:
if(rsCStrSzStrMatchRegex(f->f_filterData.prop.pCSCompValue,
- (unsigned char*) pszPropVal, 1) == RS_RET_OK)
+ (unsigned char*) pszPropVal, 1, &f->f_filterData.prop.regex_cache) == RS_RET_OK)
bRet = 1;
break;
default:
diff --git a/tools/syslogd.h b/tools/syslogd.h
index f1b11a91..8b9bd131 100644
--- a/tools/syslogd.h
+++ b/tools/syslogd.h
@@ -73,6 +73,7 @@ struct filed {
FIOP_REGEX = 4, /* matches a (BRE) regular expression? */
FIOP_EREREGEX = 5 /* matches a ERE regular expression? */
} operation;
+ regex_t *regex_cache; /* cache for compiled REs, if such are used */
cstr_t *pCSCompValue; /* value to "compare" against */
char isNegated; /* actually a boolean ;) */
} prop;