summaryrefslogtreecommitdiffstats
path: root/runtime/glbl.c
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/glbl.c')
-rw-r--r--runtime/glbl.c1523
1 files changed, 1523 insertions, 0 deletions
diff --git a/runtime/glbl.c b/runtime/glbl.c
new file mode 100644
index 0000000..6b4cb29
--- /dev/null
+++ b/runtime/glbl.c
@@ -0,0 +1,1523 @@
+/* glbl.c - this module holds global defintions and data items.
+ * These are shared among the runtime library. Their use should be
+ * limited to cases where it is actually needed. The main intension for
+ * implementing them was support for the transistion from v2 to v4
+ * (with fully modular design), but it turned out that there may also
+ * be some other good use cases besides backwards-compatibility.
+ *
+ * Module begun 2008-04-16 by Rainer Gerhards
+ *
+ * Copyright 2008-2023 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <ctype.h>
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+#include "rsyslog.h"
+#include "obj.h"
+#include "unicode-helper.h"
+#include "cfsysline.h"
+#include "glbl.h"
+#include "prop.h"
+#include "atomic.h"
+#include "errmsg.h"
+#include "action.h"
+#include "parserif.h"
+#include "rainerscript.h"
+#include "srUtils.h"
+#include "operatingstate.h"
+#include "net.h"
+#include "rsconf.h"
+#include "queue.h"
+#include "dnscache.h"
+#include "parser.h"
+#include "timezones.h"
+
+/* some defaults */
+#ifndef DFLT_NETSTRM_DRVR
+# define DFLT_NETSTRM_DRVR ((uchar*)"ptcp")
+#endif
+
+/* static data */
+DEFobjStaticHelpers
+DEFobjCurrIf(prop)
+DEFobjCurrIf(net)
+
+/* static data
+ * For this object, these variables are obviously what makes the "meat" of the
+ * class...
+ */
+
+static struct cnfobj *mainqCnfObj = NULL;/* main queue object, to be used later in startup sequence */
+static int bPreserveFQDN = 0; /* should FQDNs always be preserved? */
+static prop_t *propLocalIPIF = NULL;/* IP address to report for the local host (default is 127.0.0.1) */
+static int propLocalIPIF_set = 0; /* is propLocalIPIF already set? */
+static prop_t *propLocalHostName = NULL;/* our hostname as FQDN - read-only after startup */
+static prop_t *propLocalHostNameToDelete = NULL;/* see GenerateLocalHostName function hdr comment! */
+static uchar *LocalHostName = NULL;/* our hostname - read-only after startup, except HUP */
+static uchar *LocalHostNameOverride = NULL;/* user-overridden hostname - read-only after startup */
+static uchar *LocalFQDNName = NULL;/* our hostname as FQDN - read-only after startup, except HUP */
+static uchar *LocalDomain = NULL;/* our local domain name - read-only after startup, except HUP */
+static int iMaxLine = 8096;
+int bTerminateInputs = 0; /* global switch that inputs shall terminate ASAP (1=> terminate) */
+int glblUnloadModules = 1;
+char** glblDbgFiles = NULL;
+size_t glblDbgFilesNum = 0;
+int glblDbgWhitelist = 1;
+int glblPermitCtlC = 0;
+
+pid_t glbl_ourpid;
+#ifndef HAVE_ATOMIC_BUILTINS
+DEF_ATOMIC_HELPER_MUT(mutTerminateInputs);
+#endif
+#ifdef USE_UNLIMITED_SELECT
+static int iFdSetSize = howmany(FD_SETSIZE, __NFDBITS) * sizeof (fd_mask); /* size of select() bitmask in bytes */
+#endif
+static uchar *SourceIPofLocalClient = NULL; /* [ar] Source IP for local client to be used on multihomed host */
+
+/* tables for interfacing with the v6 config system */
+static struct cnfparamdescr cnfparamdescr[] = {
+ { "workdirectory", eCmdHdlrString, 0 },
+ { "operatingstatefile", eCmdHdlrString, 0 },
+ { "dropmsgswithmaliciousdnsptrrecords", eCmdHdlrBinary, 0 },
+ { "localhostname", eCmdHdlrGetWord, 0 },
+ { "preservefqdn", eCmdHdlrBinary, 0 },
+ { "debug.onshutdown", eCmdHdlrBinary, 0 },
+ { "debug.logfile", eCmdHdlrString, 0 },
+ { "debug.gnutls", eCmdHdlrNonNegInt, 0 },
+ { "debug.unloadmodules", eCmdHdlrBinary, 0 },
+ { "defaultnetstreamdrivercafile", eCmdHdlrString, 0 },
+ { "defaultnetstreamdrivercrlfile", eCmdHdlrString, 0 },
+ { "defaultnetstreamdriverkeyfile", eCmdHdlrString, 0 },
+ { "defaultnetstreamdrivercertfile", eCmdHdlrString, 0 },
+ { "defaultnetstreamdriver", eCmdHdlrString, 0 },
+ { "netstreamdrivercaextrafiles", eCmdHdlrString, 0 },
+ { "maxmessagesize", eCmdHdlrSize, 0 },
+ { "oversizemsg.errorfile", eCmdHdlrGetWord, 0 },
+ { "oversizemsg.report", eCmdHdlrBinary, 0 },
+ { "oversizemsg.input.mode", eCmdHdlrGetWord, 0 },
+ { "reportchildprocessexits", eCmdHdlrGetWord, 0 },
+ { "action.reportsuspension", eCmdHdlrBinary, 0 },
+ { "action.reportsuspensioncontinuation", eCmdHdlrBinary, 0 },
+ { "parser.controlcharacterescapeprefix", eCmdHdlrGetChar, 0 },
+ { "parser.droptrailinglfonreception", eCmdHdlrBinary, 0 },
+ { "parser.escapecontrolcharactersonreceive", eCmdHdlrBinary, 0 },
+ { "parser.spacelfonreceive", eCmdHdlrBinary, 0 },
+ { "parser.escape8bitcharactersonreceive", eCmdHdlrBinary, 0},
+ { "parser.escapecontrolcharactertab", eCmdHdlrBinary, 0},
+ { "parser.escapecontrolcharacterscstyle", eCmdHdlrBinary, 0 },
+ { "parser.parsehostnameandtag", eCmdHdlrBinary, 0 },
+ { "parser.permitslashinprogramname", eCmdHdlrBinary, 0 },
+ { "stdlog.channelspec", eCmdHdlrString, 0 },
+ { "janitor.interval", eCmdHdlrPositiveInt, 0 },
+ { "senders.reportnew", eCmdHdlrBinary, 0 },
+ { "senders.reportgoneaway", eCmdHdlrBinary, 0 },
+ { "senders.timeoutafter", eCmdHdlrPositiveInt, 0 },
+ { "senders.keeptrack", eCmdHdlrBinary, 0 },
+ { "inputs.timeout.shutdown", eCmdHdlrPositiveInt, 0 },
+ { "privdrop.group.keepsupplemental", eCmdHdlrBinary, 0 },
+ { "privdrop.group.id", eCmdHdlrPositiveInt, 0 },
+ { "privdrop.group.name", eCmdHdlrGID, 0 },
+ { "privdrop.user.id", eCmdHdlrPositiveInt, 0 },
+ { "privdrop.user.name", eCmdHdlrUID, 0 },
+ { "net.ipprotocol", eCmdHdlrGetWord, 0 },
+ { "net.acladdhostnameonfail", eCmdHdlrBinary, 0 },
+ { "net.aclresolvehostname", eCmdHdlrBinary, 0 },
+ { "net.enabledns", eCmdHdlrBinary, 0 },
+ { "net.permitACLwarning", eCmdHdlrBinary, 0 },
+ { "abortonuncleanconfig", eCmdHdlrBinary, 0 },
+ { "abortonfailedqueuestartup", eCmdHdlrBinary, 0 },
+ { "variables.casesensitive", eCmdHdlrBinary, 0 },
+ { "environment", eCmdHdlrArray, 0 },
+ { "processinternalmessages", eCmdHdlrBinary, 0 },
+ { "umask", eCmdHdlrFileCreateMode, 0 },
+ { "security.abortonidresolutionfail", eCmdHdlrBinary, 0 },
+ { "internal.developeronly.options", eCmdHdlrInt, 0 },
+ { "internalmsg.ratelimit.interval", eCmdHdlrPositiveInt, 0 },
+ { "internalmsg.ratelimit.burst", eCmdHdlrPositiveInt, 0 },
+ { "internalmsg.severity", eCmdHdlrSeverity, 0 },
+ { "errormessagestostderr.maxnumber", eCmdHdlrPositiveInt, 0 },
+ { "shutdown.enable.ctlc", eCmdHdlrBinary, 0 },
+ { "default.action.queue.timeoutshutdown", eCmdHdlrInt, 0 },
+ { "default.action.queue.timeoutactioncompletion", eCmdHdlrInt, 0 },
+ { "default.action.queue.timeoutenqueue", eCmdHdlrInt, 0 },
+ { "default.action.queue.timeoutworkerthreadshutdown", eCmdHdlrInt, 0 },
+ { "default.ruleset.queue.timeoutshutdown", eCmdHdlrInt, 0 },
+ { "default.ruleset.queue.timeoutactioncompletion", eCmdHdlrInt, 0 },
+ { "default.ruleset.queue.timeoutenqueue", eCmdHdlrInt, 0 },
+ { "default.ruleset.queue.timeoutworkerthreadshutdown", eCmdHdlrInt, 0 },
+ { "reverselookup.cache.ttl.default", eCmdHdlrNonNegInt, 0 },
+ { "reverselookup.cache.ttl.enable", eCmdHdlrBinary, 0 },
+ { "parser.supportcompressionextension", eCmdHdlrBinary, 0 },
+ { "shutdown.queue.doublesize", eCmdHdlrBinary, 0 },
+ { "debug.files", eCmdHdlrArray, 0 },
+ { "debug.whitelist", eCmdHdlrBinary, 0 },
+ { "libcapng.default", eCmdHdlrBinary, 0 },
+ { "libcapng.enable", eCmdHdlrBinary, 0 },
+};
+static struct cnfparamblk paramblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(cnfparamdescr)/sizeof(struct cnfparamdescr),
+ cnfparamdescr
+ };
+
+static struct cnfparamvals *cnfparamvals = NULL;
+/* we need to support multiple calls into our param block, so we need
+ * to persist the current settings. Note that this must be re-set
+ * each time a new config load begins (TODO: create interface?)
+ */
+
+int
+glblGetMaxLine(rsconf_t *cnf)
+{
+ /* glblGetMaxLine might be invoked before our configuration exists */
+ return((cnf != NULL) ? cnf->globals.iMaxLine : iMaxLine);
+}
+
+
+int
+GetGnuTLSLoglevel(rsconf_t *cnf)
+{
+ return(cnf->globals.iGnuTLSLoglevel);
+}
+
+/* define a macro for the simple properties' set and get functions
+ * (which are always the same). This is only suitable for pretty
+ * simple cases which require neither checks nor memory allocation.
+ */
+#define SIMP_PROP(nameFunc, nameVar, dataType) \
+ SIMP_PROP_GET(nameFunc, nameVar, dataType) \
+ SIMP_PROP_SET(nameFunc, nameVar, dataType)
+#define SIMP_PROP_SET(nameFunc, nameVar, dataType) \
+static rsRetVal Set##nameFunc(dataType newVal) \
+{ \
+ nameVar = newVal; \
+ return RS_RET_OK; \
+}
+#define SIMP_PROP_GET(nameFunc, nameVar, dataType) \
+static dataType Get##nameFunc(void) \
+{ \
+ return(nameVar); \
+}
+
+SIMP_PROP(PreserveFQDN, bPreserveFQDN, int)
+SIMP_PROP(mainqCnfObj, mainqCnfObj, struct cnfobj *)
+#ifdef USE_UNLIMITED_SELECT
+SIMP_PROP(FdSetSize, iFdSetSize, int)
+#endif
+
+#undef SIMP_PROP
+#undef SIMP_PROP_SET
+#undef SIMP_PROP_GET
+
+/* This is based on the previous SIMP_PROP but as a getter it uses
+ * additional parameter specifying the configuration it belongs to.
+ * The setter uses loadConf
+ */
+#define SIMP_PROP(nameFunc, nameVar, dataType) \
+ SIMP_PROP_GET(nameFunc, nameVar, dataType) \
+ SIMP_PROP_SET(nameFunc, nameVar, dataType)
+#define SIMP_PROP_SET(nameFunc, nameVar, dataType) \
+static rsRetVal Set##nameFunc(dataType newVal) \
+{ \
+ loadConf->globals.nameVar = newVal; \
+ return RS_RET_OK; \
+}
+#define SIMP_PROP_GET(nameFunc, nameVar, dataType) \
+static dataType Get##nameFunc(rsconf_t *cnf) \
+{ \
+ return(cnf->globals.nameVar); \
+}
+
+SIMP_PROP(DropMalPTRMsgs, bDropMalPTRMsgs, int)
+SIMP_PROP(DisableDNS, bDisableDNS, int)
+SIMP_PROP(ParserEscapeControlCharactersCStyle, parser.bParserEscapeCCCStyle, int)
+SIMP_PROP(ParseHOSTNAMEandTAG, parser.bParseHOSTNAMEandTAG, int)
+SIMP_PROP(OptionDisallowWarning, optionDisallowWarning, int)
+/* We omit setter on purpose, because we want to customize it */
+SIMP_PROP_GET(DfltNetstrmDrvrCAF, pszDfltNetstrmDrvrCAF, uchar*)
+SIMP_PROP_GET(DfltNetstrmDrvrCRLF, pszDfltNetstrmDrvrCRLF, uchar*)
+SIMP_PROP_GET(DfltNetstrmDrvrCertFile, pszDfltNetstrmDrvrCertFile, uchar*)
+SIMP_PROP_GET(DfltNetstrmDrvrKeyFile, pszDfltNetstrmDrvrKeyFile, uchar*)
+SIMP_PROP_GET(NetstrmDrvrCAExtraFiles, pszNetstrmDrvrCAExtraFiles, uchar*)
+SIMP_PROP_GET(ParserControlCharacterEscapePrefix, parser.cCCEscapeChar, uchar)
+SIMP_PROP_GET(ParserDropTrailingLFOnReception, parser.bDropTrailingLF, int)
+SIMP_PROP_GET(ParserEscapeControlCharactersOnReceive, parser.bEscapeCCOnRcv, int)
+SIMP_PROP_GET(ParserSpaceLFOnReceive, parser.bSpaceLFOnRcv, int)
+SIMP_PROP_GET(ParserEscape8BitCharactersOnReceive, parser.bEscape8BitChars, int)
+SIMP_PROP_GET(ParserEscapeControlCharacterTab, parser.bEscapeTab, int)
+
+#undef SIMP_PROP
+#undef SIMP_PROP_SET
+#undef SIMP_PROP_GET
+
+/* return global input termination status
+ * rgerhards, 2009-07-20
+ */
+static int GetGlobalInputTermState(void)
+{
+ return ATOMIC_FETCH_32BIT(&bTerminateInputs, &mutTerminateInputs);
+}
+
+
+/* set global termination state to "terminate". Note that this is a
+ * "once in a lifetime" action which can not be undone. -- gerhards, 2009-07-20
+ */
+static void SetGlobalInputTermination(void)
+{
+ ATOMIC_STORE_1_TO_INT(&bTerminateInputs, &mutTerminateInputs);
+}
+
+
+/* set the local host IP address to a specific string. Helper to
+ * small set of functions. No checks done, caller must ensure it is
+ * ok to call. Most importantly, the IP address must not already have
+ * been set. -- rgerhards, 2012-03-21
+ */
+static rsRetVal
+storeLocalHostIPIF(uchar *myIP)
+{
+ DEFiRet;
+ if(propLocalIPIF != NULL) {
+ CHKiRet(prop.Destruct(&propLocalIPIF));
+ }
+ CHKiRet(prop.Construct(&propLocalIPIF));
+ CHKiRet(prop.SetString(propLocalIPIF, myIP, ustrlen(myIP)));
+ CHKiRet(prop.ConstructFinalize(propLocalIPIF));
+ DBGPRINTF("rsyslog/glbl: using '%s' as localhost IP\n", myIP);
+finalize_it:
+ RETiRet;
+}
+
+
+/* This function is used to set the IP address that is to be
+ * reported for the local host. Note that in order to ease things
+ * for the v6 config interface, we do not allow this to be set more
+ * than once.
+ * rgerhards, 2012-03-21
+ */
+static rsRetVal
+setLocalHostIPIF(void __attribute__((unused)) *pVal, uchar *pNewVal)
+{
+ uchar myIP[128];
+ rsRetVal localRet;
+ DEFiRet;
+
+ CHKiRet(objUse(net, CORE_COMPONENT));
+
+ if(propLocalIPIF_set) {
+ LogError(0, RS_RET_ERR, "$LocalHostIPIF is already set "
+ "and cannot be reset; place it at TOP OF rsyslog.conf!");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ localRet = net.GetIFIPAddr(pNewVal, AF_UNSPEC, myIP, (int) sizeof(myIP));
+ if(localRet != RS_RET_OK) {
+ LogError(0, RS_RET_ERR, "$LocalHostIPIF: IP address for interface "
+ "'%s' cannnot be obtained - ignoring directive", pNewVal);
+ } else {
+ storeLocalHostIPIF(myIP);
+ }
+
+
+finalize_it:
+ free(pNewVal); /* no longer needed -> is in prop! */
+ RETiRet;
+}
+
+
+/* This function is used to set the global work directory name.
+ * It verifies that the provided directory actually exists and
+ * emits an error message if not.
+ * rgerhards, 2011-02-16
+ */
+static rsRetVal setWorkDir(void __attribute__((unused)) *pVal, uchar *pNewVal)
+{
+ size_t lenDir;
+ int i;
+ struct stat sb;
+ DEFiRet;
+
+ /* remove trailing slashes */
+ lenDir = ustrlen(pNewVal);
+ i = lenDir - 1;
+ while(i > 0 && pNewVal[i] == '/') {
+ --i;
+ }
+
+ if(i < 0) {
+ LogError(0, RS_RET_ERR_WRKDIR, "$WorkDirectory: empty value "
+ "- directive ignored");
+ ABORT_FINALIZE(RS_RET_ERR_WRKDIR);
+ }
+
+ if(i != (int) lenDir - 1) {
+ pNewVal[i+1] = '\0';
+ LogError(0, RS_RET_WRN_WRKDIR, "$WorkDirectory: trailing slashes "
+ "removed, new value is '%s'", pNewVal);
+ }
+
+ if(stat((char*) pNewVal, &sb) != 0) {
+ LogError(0, RS_RET_ERR_WRKDIR, "$WorkDirectory: %s can not be "
+ "accessed, probably does not exist - directive ignored", pNewVal);
+ ABORT_FINALIZE(RS_RET_ERR_WRKDIR);
+ }
+
+ if(!S_ISDIR(sb.st_mode)) {
+ LogError(0, RS_RET_ERR_WRKDIR, "$WorkDirectory: %s not a directory - directive ignored",
+ pNewVal);
+ ABORT_FINALIZE(RS_RET_ERR_WRKDIR);
+ }
+
+ free(loadConf->globals.pszWorkDir);
+ loadConf->globals.pszWorkDir = pNewVal;
+
+finalize_it:
+ RETiRet;
+}
+
+
+static rsRetVal
+setDfltNetstrmDrvrCAF(void __attribute__((unused)) *pVal, uchar *pNewVal) {
+ DEFiRet;
+ FILE *fp;
+ free(loadConf->globals.pszDfltNetstrmDrvrCAF);
+ loadConf->globals.pszDfltNetstrmDrvrCAF = pNewVal;
+ fp = fopen((const char*)pNewVal, "r");
+ if(fp == NULL) {
+ LogError(errno, RS_RET_NO_FILE_ACCESS,
+ "error: defaultnetstreamdrivercafile file '%s' "
+ "could not be accessed", pNewVal);
+ } else {
+ fclose(fp);
+ }
+
+ RETiRet;
+}
+
+static rsRetVal
+setNetstrmDrvrCAExtraFiles(void __attribute__((unused)) *pVal, uchar *pNewVal) {
+ DEFiRet;
+ FILE *fp;
+ char* token;
+ int error = 0;
+ free(loadConf->globals.pszNetstrmDrvrCAExtraFiles);
+
+ token = strtok((char*)pNewVal, ",");
+ // Here, fopen per strtok ...
+ while(token != NULL) {
+ fp = fopen((const char*)token, "r");
+ if(fp == NULL) {
+ LogError(errno, RS_RET_NO_FILE_ACCESS,
+ "error: netstreamdrivercaextrafiles file '%s' "
+ "could not be accessed", token);
+ error = 1;
+ } else {
+ fclose(fp);
+ }
+ token = strtok(NULL, ",");
+ }
+ if(!error) {
+ loadConf->globals.pszNetstrmDrvrCAExtraFiles = pNewVal;
+ } else {
+ loadConf->globals.pszNetstrmDrvrCAExtraFiles = NULL;
+ }
+ RETiRet;
+}
+
+static rsRetVal
+setDfltNetstrmDrvrCRLF(void __attribute__((unused)) *pVal, uchar *pNewVal) {
+ DEFiRet;
+ FILE *fp;
+ free(loadConf->globals.pszDfltNetstrmDrvrCRLF);
+ loadConf->globals.pszDfltNetstrmDrvrCRLF = pNewVal;
+ fp = fopen((const char*)pNewVal, "r");
+ if(fp == NULL) {
+ LogError(errno, RS_RET_NO_FILE_ACCESS,
+ "error: defaultnetstreamdrivercrlfile file '%s' "
+ "could not be accessed", pNewVal);
+ } else {
+ fclose(fp);
+ }
+
+ RETiRet;
+}
+
+
+static rsRetVal
+setDfltNetstrmDrvrCertFile(void __attribute__((unused)) *pVal, uchar *pNewVal) {
+ DEFiRet;
+ FILE *fp;
+
+ free(loadConf->globals.pszDfltNetstrmDrvrCertFile);
+ loadConf->globals.pszDfltNetstrmDrvrCertFile = pNewVal;
+ fp = fopen((const char*)pNewVal, "r");
+ if(fp == NULL) {
+ LogError(errno, RS_RET_NO_FILE_ACCESS,
+ "error: defaultnetstreamdrivercertfile '%s' "
+ "could not be accessed", pNewVal);
+ } else {
+ fclose(fp);
+ }
+
+ RETiRet;
+}
+
+static rsRetVal
+setDfltNetstrmDrvrKeyFile(void __attribute__((unused)) *pVal, uchar *pNewVal) {
+ DEFiRet;
+ FILE *fp;
+
+ free(loadConf->globals.pszDfltNetstrmDrvrKeyFile);
+ loadConf->globals.pszDfltNetstrmDrvrKeyFile = pNewVal;
+ fp = fopen((const char*)pNewVal, "r");
+ if(fp == NULL) {
+ LogError(errno, RS_RET_NO_FILE_ACCESS,
+ "error: defaultnetstreamdriverkeyfile '%s' "
+ "could not be accessed", pNewVal);
+ } else {
+ fclose(fp);
+ }
+
+ RETiRet;
+}
+
+static rsRetVal
+setDfltNetstrmDrvr(void __attribute__((unused)) *pVal, uchar *pNewVal) {
+ DEFiRet;
+ free(loadConf->globals.pszDfltNetstrmDrvr);
+ loadConf->globals.pszDfltNetstrmDrvr = pNewVal;
+ RETiRet;
+}
+
+static rsRetVal
+setParserControlCharacterEscapePrefix(void __attribute__((unused)) *pVal, uchar *pNewVal) {
+ DEFiRet;
+ loadConf->globals.parser.cCCEscapeChar = *pNewVal;
+ RETiRet;
+}
+
+static rsRetVal
+setParserDropTrailingLFOnReception(void __attribute__((unused)) *pVal, int pNewVal) {
+ DEFiRet;
+ loadConf->globals.parser.bDropTrailingLF = pNewVal;
+ RETiRet;
+}
+
+static rsRetVal
+setParserEscapeControlCharactersOnReceive(void __attribute__((unused)) *pVal, int pNewVal) {
+ DEFiRet;
+ loadConf->globals.parser.bEscapeCCOnRcv = pNewVal;
+ RETiRet;
+}
+
+static rsRetVal
+setParserSpaceLFOnReceive(void __attribute__((unused)) *pVal, int pNewVal) {
+ DEFiRet;
+ loadConf->globals.parser.bSpaceLFOnRcv = pNewVal;
+ RETiRet;
+}
+
+static rsRetVal
+setParserEscape8BitCharactersOnReceive(void __attribute__((unused)) *pVal, int pNewVal) {
+ DEFiRet;
+ loadConf->globals.parser.bEscape8BitChars = pNewVal;
+ RETiRet;
+}
+
+static rsRetVal
+setParserEscapeControlCharacterTab(void __attribute__((unused)) *pVal, int pNewVal) {
+ DEFiRet;
+ loadConf->globals.parser.bEscapeTab = pNewVal;
+ RETiRet;
+}
+
+/* This function is used both by legacy and RainerScript conf. It is a real setter. */
+static void
+setMaxLine(const int64_t iNew)
+{
+ if(iNew < 128) {
+ LogError(0, RS_RET_INVALID_VALUE, "maxMessageSize tried to set "
+ "to %lld, but cannot be less than 128 - set to 128 "
+ "instead", (long long) iNew);
+ loadConf->globals.iMaxLine = 128;
+ } else if(iNew > (int64_t) INT_MAX) {
+ LogError(0, RS_RET_INVALID_VALUE, "maxMessageSize larger than "
+ "INT_MAX (%d) - reduced to INT_MAX", INT_MAX);
+ loadConf->globals.iMaxLine = INT_MAX;
+ } else {
+ loadConf->globals.iMaxLine = (int) iNew;
+ }
+}
+
+
+
+static rsRetVal
+legacySetMaxMessageSize(void __attribute__((unused)) *pVal, int64_t iNew)
+{
+ setMaxLine(iNew);
+ return RS_RET_OK;
+}
+
+static rsRetVal
+setDebugFile(void __attribute__((unused)) *pVal, uchar *pNewVal)
+{
+ DEFiRet;
+ dbgSetDebugFile(pNewVal);
+ free(pNewVal);
+ RETiRet;
+}
+
+static rsRetVal
+setDebugLevel(void __attribute__((unused)) *pVal, int level)
+{
+ DEFiRet;
+ dbgSetDebugLevel(level);
+ dbgprintf("debug level %d set via config file\n", level);
+ dbgprintf("This is rsyslog version " VERSION "\n");
+ RETiRet;
+}
+
+static rsRetVal ATTR_NONNULL()
+setOversizeMsgInputMode(const uchar *const mode)
+{
+ DEFiRet;
+ if(!strcmp((char*)mode, "truncate")) {
+ loadConf->globals.oversizeMsgInputMode = glblOversizeMsgInputMode_Truncate;
+ } else if(!strcmp((char*)mode, "split")) {
+ loadConf->globals.oversizeMsgInputMode = glblOversizeMsgInputMode_Split;
+ } else if(!strcmp((char*)mode, "accept")) {
+ loadConf->globals.oversizeMsgInputMode = glblOversizeMsgInputMode_Accept;
+ } else {
+ loadConf->globals.oversizeMsgInputMode = glblOversizeMsgInputMode_Truncate;
+ }
+ RETiRet;
+}
+
+static rsRetVal ATTR_NONNULL()
+setReportChildProcessExits(const uchar *const mode)
+{
+ DEFiRet;
+ if(!strcmp((char*)mode, "none")) {
+ loadConf->globals.reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_NONE;
+ } else if(!strcmp((char*)mode, "errors")) {
+ loadConf->globals.reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_ERRORS;
+ } else if(!strcmp((char*)mode, "all")) {
+ loadConf->globals.reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_ALL;
+ } else {
+ LogError(0, RS_RET_CONF_PARAM_INVLD,
+ "invalid value '%s' for global parameter reportChildProcessExits -- ignored",
+ mode);
+ iRet = RS_RET_CONF_PARAM_INVLD;
+ }
+ RETiRet;
+}
+
+static int
+getDefPFFamily(rsconf_t *cnf)
+{
+ return cnf->globals.iDefPFFamily;
+}
+
+/* return our local IP.
+ * If no local IP is set, "127.0.0.1" is selected *and* set. This
+ * is an intensional side effect that we do in order to keep things
+ * consistent and avoid config errors (this will make us not accept
+ * setting the local IP address once a module has obtained it - so
+ * it forces the $LocalHostIPIF directive high up in rsyslog.conf)
+ * rgerhards, 2012-03-21
+ */
+static prop_t*
+GetLocalHostIP(void)
+{
+ assert(propLocalIPIF != NULL);
+ return(propLocalIPIF);
+}
+
+
+/* set our local hostname. Free previous hostname, if it was already set.
+ * Note that we do now do this in a thread. As such, the method here
+ * is NOT 100% clean. If we run into issues, we need to think about
+ * refactoring the whole way we handle the local host name processing.
+ * Possibly using a PROP might be the right solution then.
+ */
+static rsRetVal
+SetLocalHostName(uchar *const newname)
+{
+ uchar *toFree;
+ if(LocalHostName == NULL || strcmp((const char*)LocalHostName, (const char*) newname)) {
+ toFree = LocalHostName;
+ LocalHostName = newname;
+ } else {
+ toFree = newname;
+ }
+ free(toFree);
+ return RS_RET_OK;
+}
+
+
+/* return our local hostname. if it is not set, "[localhost]" is returned
+ */
+uchar*
+glblGetLocalHostName(void)
+{
+ uchar *pszRet;
+
+ if(LocalHostNameOverride != NULL) {
+ pszRet = LocalHostNameOverride;
+ goto done;
+ }
+
+ if(LocalHostName == NULL)
+ pszRet = (uchar*) "[localhost]";
+ else {
+ if(GetPreserveFQDN() == 1)
+ pszRet = LocalFQDNName;
+ else
+ pszRet = LocalHostName;
+ }
+done:
+ return(pszRet);
+}
+
+
+/* return the name of the file where oversize messages are written to
+ */
+uchar*
+glblGetOversizeMsgErrorFile(rsconf_t *cnf)
+{
+ return cnf->globals.oversizeMsgErrorFile;
+}
+
+const uchar*
+glblGetOperatingStateFile(rsconf_t *cnf)
+{
+ return cnf->globals.operatingStateFile;
+}
+
+/* return the mode with which oversize messages will be put forward
+ */
+int
+glblGetOversizeMsgInputMode(rsconf_t *cnf)
+{
+ return cnf->globals.oversizeMsgInputMode;
+}
+
+int
+glblReportOversizeMessage(rsconf_t *cnf)
+{
+ return cnf->globals.reportOversizeMsg;
+}
+
+
+/* logs a message indicating that a child process has terminated.
+ * If name != NULL, prints it as the program name.
+ */
+void
+glblReportChildProcessExit(rsconf_t *cnf, const uchar *name, pid_t pid, int status)
+{
+ DBGPRINTF("waitpid for child %ld returned status: %2.2x\n", (long) pid, status);
+
+ if(cnf->globals.reportChildProcessExits == REPORT_CHILD_PROCESS_EXITS_NONE
+ || (cnf->globals.reportChildProcessExits == REPORT_CHILD_PROCESS_EXITS_ERRORS
+ && WIFEXITED(status) && WEXITSTATUS(status) == 0)) {
+ return;
+ }
+
+ if(WIFEXITED(status)) {
+ int severity = WEXITSTATUS(status) == 0 ? LOG_INFO : LOG_WARNING;
+ if(name != NULL) {
+ LogMsg(0, NO_ERRCODE, severity, "program '%s' (pid %ld) exited with status %d",
+ name, (long) pid, WEXITSTATUS(status));
+ } else {
+ LogMsg(0, NO_ERRCODE, severity, "child process (pid %ld) exited with status %d",
+ (long) pid, WEXITSTATUS(status));
+ }
+ } else if(WIFSIGNALED(status)) {
+ if(name != NULL) {
+ LogMsg(0, NO_ERRCODE, LOG_WARNING, "program '%s' (pid %ld) terminated by signal %d",
+ name, (long) pid, WTERMSIG(status));
+ } else {
+ LogMsg(0, NO_ERRCODE, LOG_WARNING, "child process (pid %ld) terminated by signal %d",
+ (long) pid, WTERMSIG(status));
+ }
+ }
+}
+
+
+/* set our local domain name. Free previous domain, if it was already set.
+ */
+static rsRetVal
+SetLocalDomain(uchar *newname)
+{
+ free(LocalDomain);
+ LocalDomain = newname;
+ return RS_RET_OK;
+}
+
+
+/* return our local hostname. if it is not set, "[localhost]" is returned
+ */
+static uchar*
+GetLocalDomain(void)
+{
+ return LocalDomain;
+}
+
+
+/* generate the local hostname property. This must be done after the hostname info
+ * has been set as well as PreserveFQDN.
+ * rgerhards, 2009-06-30
+ * NOTE: This function tries to avoid locking by not destructing the previous value
+ * immediately. This is so that current readers can continue to use the previous name.
+ * Otherwise, we would need to use read/write locks to protect the update process.
+ * In order to do so, we save the previous value and delete it when we are called again
+ * the next time. Note that this in theory is racy and can lead to a double-free.
+ * In practice, however, the window of exposure to trigger this is extremely short
+ * and as this functions is very infrequently being called (on HUP), the trigger
+ * condition for this bug is so highly unlikely that it never occurs in practice.
+ * Probably if you HUP rsyslog every few milliseconds, but who does that...
+ * To further reduce risk potential, we do only update the property when there
+ * actually is a hostname change, which makes it even less likely.
+ * rgerhards, 2013-10-28
+ */
+static rsRetVal
+GenerateLocalHostNameProperty(void)
+{
+ uchar *pszPrev;
+ int lenPrev;
+ prop_t *hostnameNew;
+ uchar *pszName;
+ DEFiRet;
+
+ if(propLocalHostNameToDelete != NULL)
+ prop.Destruct(&propLocalHostNameToDelete);
+
+ if(LocalHostNameOverride == NULL) {
+ if(LocalHostName == NULL)
+ pszName = (uchar*) "[localhost]";
+ else {
+ if(GetPreserveFQDN() == 1)
+ pszName = LocalFQDNName;
+ else
+ pszName = LocalHostName;
+ }
+ } else { /* local hostname is overriden via config */
+ pszName = LocalHostNameOverride;
+ }
+ DBGPRINTF("GenerateLocalHostName uses '%s'\n", pszName);
+
+ if(propLocalHostName == NULL)
+ pszPrev = (uchar*)""; /* make sure strcmp() below does not match */
+ else
+ prop.GetString(propLocalHostName, &pszPrev, &lenPrev);
+
+ if(ustrcmp(pszPrev, pszName)) {
+ /* we need to update */
+ CHKiRet(prop.Construct(&hostnameNew));
+ CHKiRet(prop.SetString(hostnameNew, pszName, ustrlen(pszName)));
+ CHKiRet(prop.ConstructFinalize(hostnameNew));
+ propLocalHostNameToDelete = propLocalHostName;
+ propLocalHostName = hostnameNew;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* return our local hostname as a string property
+ */
+static prop_t*
+GetLocalHostNameProp(void)
+{
+ return(propLocalHostName);
+}
+
+
+static rsRetVal
+SetLocalFQDNName(uchar *newname)
+{
+ free(LocalFQDNName);
+ LocalFQDNName = newname;
+ return RS_RET_OK;
+}
+
+/* return the current localhost name as FQDN (requires FQDN to be set)
+ * TODO: we should set the FQDN ourselfs in here!
+ */
+static uchar*
+GetLocalFQDNName(void)
+{
+ return(LocalFQDNName == NULL ? (uchar*) "[localhost]" : LocalFQDNName);
+}
+
+
+/* return the current working directory */
+static uchar*
+GetWorkDir(rsconf_t *cnf)
+{
+ return(cnf->globals.pszWorkDir == NULL ? (uchar*) "" : cnf->globals.pszWorkDir);
+}
+
+/* return the "raw" working directory, which means
+ * NULL if unset.
+ */
+const uchar *
+glblGetWorkDirRaw(rsconf_t *cnf)
+{
+ return cnf->globals.pszWorkDir;
+}
+
+/* return the current default netstream driver */
+static uchar*
+GetDfltNetstrmDrvr(rsconf_t *cnf)
+{
+ return(cnf->globals.pszDfltNetstrmDrvr == NULL ? DFLT_NETSTRM_DRVR : cnf->globals.pszDfltNetstrmDrvr);
+}
+
+/* [ar] Source IP for local client to be used on multihomed host */
+static rsRetVal
+SetSourceIPofLocalClient(uchar *newname)
+{
+ if(SourceIPofLocalClient != NULL) {
+ free(SourceIPofLocalClient); }
+ SourceIPofLocalClient = newname;
+ return RS_RET_OK;
+}
+
+static uchar*
+GetSourceIPofLocalClient(void)
+{
+ return(SourceIPofLocalClient);
+}
+
+
+/* queryInterface function
+ * rgerhards, 2008-02-21
+ */
+BEGINobjQueryInterface(glbl)
+CODESTARTobjQueryInterface(glbl)
+ if(pIf->ifVersion != glblCURR_IF_VERSION) { /* check for current version, increment on each change */
+ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
+ }
+
+ /* ok, we have the right interface, so let's fill it
+ * Please note that we may also do some backwards-compatibility
+ * work here (if we can support an older interface version - that,
+ * of course, also affects the "if" above).
+ */
+ pIf->GetWorkDir = GetWorkDir;
+ pIf->GenerateLocalHostNameProperty = GenerateLocalHostNameProperty;
+ pIf->GetLocalHostNameProp = GetLocalHostNameProp;
+ pIf->GetLocalHostIP = GetLocalHostIP;
+ pIf->SetGlobalInputTermination = SetGlobalInputTermination;
+ pIf->GetGlobalInputTermState = GetGlobalInputTermState;
+ pIf->GetSourceIPofLocalClient = GetSourceIPofLocalClient; /* [ar] */
+ pIf->SetSourceIPofLocalClient = SetSourceIPofLocalClient; /* [ar] */
+ pIf->GetDefPFFamily = getDefPFFamily;
+ pIf->GetDisableDNS = GetDisableDNS;
+ pIf->GetMaxLine = glblGetMaxLine;
+ pIf->GetOptionDisallowWarning = GetOptionDisallowWarning;
+ pIf->GetDfltNetstrmDrvrCAF = GetDfltNetstrmDrvrCAF;
+ pIf->GetDfltNetstrmDrvrCRLF = GetDfltNetstrmDrvrCRLF;
+ pIf->GetDfltNetstrmDrvrCertFile = GetDfltNetstrmDrvrCertFile;
+ pIf->GetDfltNetstrmDrvrKeyFile = GetDfltNetstrmDrvrKeyFile;
+ pIf->GetDfltNetstrmDrvr = GetDfltNetstrmDrvr;
+ pIf->GetNetstrmDrvrCAExtraFiles = GetNetstrmDrvrCAExtraFiles;
+ pIf->GetParserControlCharacterEscapePrefix = GetParserControlCharacterEscapePrefix;
+ pIf->GetParserDropTrailingLFOnReception = GetParserDropTrailingLFOnReception;
+ pIf->GetParserEscapeControlCharactersOnReceive = GetParserEscapeControlCharactersOnReceive;
+ pIf->GetParserSpaceLFOnReceive = GetParserSpaceLFOnReceive;
+ pIf->GetParserEscape8BitCharactersOnReceive = GetParserEscape8BitCharactersOnReceive;
+ pIf->GetParserEscapeControlCharacterTab = GetParserEscapeControlCharacterTab;
+ pIf->GetLocalHostName = glblGetLocalHostName;
+ pIf->SetLocalHostName = SetLocalHostName;
+#define SIMP_PROP(name) \
+ pIf->Get##name = Get##name; \
+ pIf->Set##name = Set##name;
+ SIMP_PROP(PreserveFQDN);
+ SIMP_PROP(DropMalPTRMsgs);
+ SIMP_PROP(mainqCnfObj);
+ SIMP_PROP(LocalFQDNName)
+ SIMP_PROP(LocalDomain)
+ SIMP_PROP(ParserEscapeControlCharactersCStyle)
+ SIMP_PROP(ParseHOSTNAMEandTAG)
+#ifdef USE_UNLIMITED_SELECT
+ SIMP_PROP(FdSetSize)
+#endif
+#undef SIMP_PROP
+finalize_it:
+ENDobjQueryInterface(glbl)
+
+/* Reset config variables to default values.
+ * rgerhards, 2008-04-17
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ free(loadConf->globals.pszDfltNetstrmDrvr);
+ loadConf->globals.pszDfltNetstrmDrvr = NULL;
+ free(loadConf->globals.pszDfltNetstrmDrvrCAF);
+ loadConf->globals.pszDfltNetstrmDrvrCAF = NULL;
+ free(loadConf->globals.pszDfltNetstrmDrvrCRLF);
+ loadConf->globals.pszDfltNetstrmDrvrCRLF = NULL;
+ free(loadConf->globals.pszDfltNetstrmDrvrKeyFile);
+ loadConf->globals.pszDfltNetstrmDrvrKeyFile = NULL;
+ free(loadConf->globals.pszDfltNetstrmDrvrCertFile);
+ loadConf->globals.pszDfltNetstrmDrvrCertFile = NULL;
+ free(LocalHostNameOverride);
+ LocalHostNameOverride = NULL;
+ free(loadConf->globals.oversizeMsgErrorFile);
+ loadConf->globals.oversizeMsgErrorFile = NULL;
+ loadConf->globals.oversizeMsgInputMode = glblOversizeMsgInputMode_Accept;
+ loadConf->globals.reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_ERRORS;
+ free(loadConf->globals.pszWorkDir);
+ loadConf->globals.pszWorkDir = NULL;
+ free((void*)loadConf->globals.operatingStateFile);
+ loadConf->globals.operatingStateFile = NULL;
+ loadConf->globals.bDropMalPTRMsgs = 0;
+ bPreserveFQDN = 0;
+ loadConf->globals.iMaxLine = 8192;
+ loadConf->globals.reportOversizeMsg = 1;
+ loadConf->globals.parser.cCCEscapeChar = '#';
+ loadConf->globals.parser.bDropTrailingLF = 1;
+ loadConf->globals.parser.bEscapeCCOnRcv = 1; /* default is to escape control characters */
+ loadConf->globals.parser.bSpaceLFOnRcv = 0;
+ loadConf->globals.parser.bEscape8BitChars = 0; /* default is not to escape control characters */
+ loadConf->globals.parser.bEscapeTab = 1; /* default is to escape tab characters */
+ loadConf->globals.parser.bParserEscapeCCCStyle = 0;
+#ifdef USE_UNLIMITED_SELECT
+ iFdSetSize = howmany(FD_SETSIZE, __NFDBITS) * sizeof (fd_mask);
+#endif
+ return RS_RET_OK;
+}
+
+
+/* Prepare for new config
+ */
+void
+glblPrepCnf(void)
+{
+ free(mainqCnfObj);
+ mainqCnfObj = NULL;
+ free(cnfparamvals);
+ cnfparamvals = NULL;
+}
+
+/* handle the timezone() object. Each incarnation adds one additional
+ * zone info to the global table of time zones.
+ */
+
+int
+bs_arrcmp_glblDbgFiles(const void *s1, const void *s2)
+{
+ return strcmp((char*)s1, *(char**)s2);
+}
+
+
+
+/* handle a global config object. Note that multiple global config statements
+ * are permitted (because of plugin support), so once we got a param block,
+ * we need to hold to it.
+ * rgerhards, 2011-07-19
+ */
+void
+glblProcessCnf(struct cnfobj *o)
+{
+ int i;
+
+ cnfparamvals = nvlstGetParams(o->nvlst, &paramblk, cnfparamvals);
+ if(cnfparamvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing global "
+ "config parameters [global(...)]");
+ goto done;
+ }
+ if(Debug) {
+ dbgprintf("glbl param blk after glblProcessCnf:\n");
+ cnfparamsPrint(&paramblk, cnfparamvals);
+ }
+
+ /* The next thing is a bit hackish and should be changed in higher
+ * versions. There are a select few parameters which we need to
+ * act on immediately. These are processed here.
+ */
+ for(i = 0 ; i < paramblk.nParams ; ++i) {
+ if(!cnfparamvals[i].bUsed)
+ continue;
+ if(!strcmp(paramblk.descr[i].name, "processinternalmessages")) {
+ loadConf->globals.bProcessInternalMessages = (int) cnfparamvals[i].val.d.n;
+ cnfparamvals[i].bUsed = TRUE;
+ } else if(!strcmp(paramblk.descr[i].name, "internal.developeronly.options")) {
+ loadConf->globals.glblDevOptions = (uint64_t) cnfparamvals[i].val.d.n;
+ cnfparamvals[i].bUsed = TRUE;
+ } else if(!strcmp(paramblk.descr[i].name, "stdlog.channelspec")) {
+#ifndef ENABLE_LIBLOGGING_STDLOG
+ LogError(0, RS_RET_ERR, "rsyslog wasn't "
+ "compiled with liblogging-stdlog support. "
+ "The 'stdlog.channelspec' parameter "
+ "is ignored. Note: the syslog API is used instead.\n");
+#else
+ loadConf->globals.stdlog_chanspec = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ /* we need to re-open with the new channel */
+ stdlog_close(loadConf->globals.stdlog_hdl);
+ loadConf->globals.stdlog_hdl = stdlog_open("rsyslogd", 0, STDLOG_SYSLOG,
+ (char*) loadConf->globals.stdlog_chanspec);
+ cnfparamvals[i].bUsed = TRUE;
+#endif
+ } else if(!strcmp(paramblk.descr[i].name, "operatingstatefile")) {
+ if(loadConf->globals.operatingStateFile != NULL) {
+ LogError(errno, RS_RET_PARAM_ERROR,
+ "error: operatingStateFile already set to '%s' - "
+ "new value ignored", loadConf->globals.operatingStateFile);
+ } else {
+ loadConf->globals.operatingStateFile =
+ (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ osf_open();
+ }
+ } else if(!strcmp(paramblk.descr[i].name, "security.abortonidresolutionfail")) {
+ loadConf->globals.abortOnIDResolutionFail = (int) cnfparamvals[i].val.d.n;
+ cnfparamvals[i].bUsed = TRUE;
+ }
+ }
+done: return;
+}
+
+/* Set mainq parameters. Note that when this is not called, we'll use the
+ * legacy parameter config. mainq parameters can only be set once.
+ */
+void
+glblProcessMainQCnf(struct cnfobj *o)
+{
+ if(mainqCnfObj == NULL) {
+ mainqCnfObj = o;
+ } else {
+ LogError(0, RS_RET_ERR, "main_queue() object can only be specified "
+ "once - all but first ignored\n");
+ }
+}
+
+/* destruct the main q cnf object after it is no longer needed. This is
+ * also used to do some final checks.
+ */
+void
+glblDestructMainqCnfObj(void)
+{
+ /* Only destruct if not NULL! */
+ if (mainqCnfObj != NULL) {
+ nvlstChkUnused(mainqCnfObj->nvlst);
+ cnfobjDestruct(mainqCnfObj);
+ mainqCnfObj = NULL;
+ }
+}
+
+static int
+qs_arrcmp_glblDbgFiles(const void *s1, const void *s2)
+{
+ return strcmp(*((char**)s1), *((char**)s2));
+}
+
+/* set an environment variable */
+static rsRetVal
+do_setenv(const char *const var)
+{
+ char varname[128];
+ const char *val = var;
+ size_t i;
+ DEFiRet;
+
+ for(i = 0 ; *val != '=' ; ++i, ++val) {
+ if(i == sizeof(varname)-i) {
+ parser_errmsg("environment variable name too long "
+ "[max %zu chars] or malformed entry: '%s'",
+ sizeof(varname)-1, var);
+ ABORT_FINALIZE(RS_RET_ERR_SETENV);
+ }
+ if(*val == '\0') {
+ parser_errmsg("environment variable entry is missing "
+ "equal sign (for value): '%s'", var);
+ ABORT_FINALIZE(RS_RET_ERR_SETENV);
+ }
+ varname[i] = *val;
+ }
+ varname[i] = '\0';
+ ++val;
+ DBGPRINTF("do_setenv, var '%s', val '%s'\n", varname, val);
+
+ if(setenv(varname, val, 1) != 0) {
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ parser_errmsg("error setting environment variable "
+ "'%s' to '%s': %s", varname, val, errStr);
+ ABORT_FINALIZE(RS_RET_ERR_SETENV);
+ }
+
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* This processes the "regular" parameters which are to be set after the
+ * config has been fully loaded.
+ */
+rsRetVal
+glblDoneLoadCnf(void)
+{
+ int i;
+ unsigned char *cstr;
+ DEFiRet;
+ CHKiRet(objUse(net, CORE_COMPONENT));
+
+ sortTimezones(loadConf);
+ DBGPRINTF("Timezone information table (%d entries):\n", loadConf->timezones.ntzinfos);
+ displayTimezones(loadConf);
+
+ if(cnfparamvals == NULL)
+ goto finalize_it;
+
+ for(i = 0 ; i < paramblk.nParams ; ++i) {
+ if(!cnfparamvals[i].bUsed)
+ continue;
+ if(!strcmp(paramblk.descr[i].name, "workdirectory")) {
+ cstr = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ setWorkDir(NULL, cstr);
+ } else if(!strcmp(paramblk.descr[i].name, "libcapng.default")) {
+#ifdef ENABLE_LIBCAPNG
+ loadConf->globals.bAbortOnFailedLibcapngSetup = (int) cnfparamvals[i].val.d.n;
+#else
+ LogError(0, RS_RET_ERR, "rsyslog wasn't "
+ "compiled with libcap-ng support.");
+#endif
+ } else if(!strcmp(paramblk.descr[i].name, "libcapng.enable")) {
+#ifdef ENABLE_LIBCAPNG
+ loadConf->globals.bCapabilityDropEnabled = (int) cnfparamvals[i].val.d.n;
+#else
+ LogError(0, RS_RET_ERR, "rsyslog wasn't "
+ "compiled with libcap-ng support.");
+#endif
+ } else if(!strcmp(paramblk.descr[i].name, "variables.casesensitive")) {
+ const int val = (int) cnfparamvals[i].val.d.n;
+ fjson_global_do_case_sensitive_comparison(val);
+ DBGPRINTF("global/config: set case sensitive variables to %d\n",
+ val);
+ } else if(!strcmp(paramblk.descr[i].name, "localhostname")) {
+ free(LocalHostNameOverride);
+ LocalHostNameOverride = (uchar*)
+ es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ } else if(!strcmp(paramblk.descr[i].name, "defaultnetstreamdriverkeyfile")) {
+ cstr = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ setDfltNetstrmDrvrKeyFile(NULL, cstr);
+ } else if(!strcmp(paramblk.descr[i].name, "defaultnetstreamdrivercertfile")) {
+ cstr = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ setDfltNetstrmDrvrCertFile(NULL, cstr);
+ } else if(!strcmp(paramblk.descr[i].name, "defaultnetstreamdrivercafile")) {
+ cstr = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ setDfltNetstrmDrvrCAF(NULL, cstr);
+ } else if(!strcmp(paramblk.descr[i].name, "defaultnetstreamdrivercrlfile")) {
+ cstr = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ setDfltNetstrmDrvrCRLF(NULL, cstr);
+ } else if(!strcmp(paramblk.descr[i].name, "defaultnetstreamdriver")) {
+ cstr = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ setDfltNetstrmDrvr(NULL, cstr);
+ } else if(!strcmp(paramblk.descr[i].name, "netstreamdrivercaextrafiles")) {
+ cstr = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ setNetstrmDrvrCAExtraFiles(NULL, cstr);
+ } else if(!strcmp(paramblk.descr[i].name, "preservefqdn")) {
+ bPreserveFQDN = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name,
+ "dropmsgswithmaliciousdnsptrrecords")) {
+ loadConf->globals.bDropMalPTRMsgs = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "action.reportsuspension")) {
+ loadConf->globals.bActionReportSuspension = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "action.reportsuspensioncontinuation")) {
+ loadConf->globals.bActionReportSuspensionCont = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "maxmessagesize")) {
+ setMaxLine(cnfparamvals[i].val.d.n);
+ } else if(!strcmp(paramblk.descr[i].name, "oversizemsg.errorfile")) {
+ free(loadConf->globals.oversizeMsgErrorFile);
+ loadConf->globals.oversizeMsgErrorFile = (uchar*)es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ } else if(!strcmp(paramblk.descr[i].name, "oversizemsg.report")) {
+ loadConf->globals.reportOversizeMsg = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "oversizemsg.input.mode")) {
+ const char *const tmp = es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ setOversizeMsgInputMode((uchar*) tmp);
+ free((void*)tmp);
+ } else if(!strcmp(paramblk.descr[i].name, "reportchildprocessexits")) {
+ const char *const tmp = es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ setReportChildProcessExits((uchar*) tmp);
+ free((void*)tmp);
+ } else if(!strcmp(paramblk.descr[i].name, "debug.onshutdown")) {
+ loadConf->globals.debugOnShutdown = (int) cnfparamvals[i].val.d.n;
+ LogError(0, RS_RET_OK, "debug: onShutdown set to %d", loadConf->globals.debugOnShutdown);
+ } else if(!strcmp(paramblk.descr[i].name, "debug.gnutls")) {
+ loadConf->globals.iGnuTLSLoglevel = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "debug.unloadmodules")) {
+ glblUnloadModules = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "parser.controlcharacterescapeprefix")) {
+ uchar* tmp = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ setParserControlCharacterEscapePrefix(NULL, tmp);
+ free(tmp);
+ } else if(!strcmp(paramblk.descr[i].name, "parser.droptrailinglfonreception")) {
+ const int tmp = (int) cnfparamvals[i].val.d.n;
+ setParserDropTrailingLFOnReception(NULL, tmp);
+ } else if(!strcmp(paramblk.descr[i].name, "parser.escapecontrolcharactersonreceive")) {
+ const int tmp = (int) cnfparamvals[i].val.d.n;
+ setParserEscapeControlCharactersOnReceive(NULL, tmp);
+ } else if(!strcmp(paramblk.descr[i].name, "parser.spacelfonreceive")) {
+ const int tmp = (int) cnfparamvals[i].val.d.n;
+ setParserSpaceLFOnReceive(NULL, tmp);
+ } else if(!strcmp(paramblk.descr[i].name, "parser.escape8bitcharactersonreceive")) {
+ const int tmp = (int) cnfparamvals[i].val.d.n;
+ setParserEscape8BitCharactersOnReceive(NULL, tmp);
+ } else if(!strcmp(paramblk.descr[i].name, "parser.escapecontrolcharactertab")) {
+ const int tmp = (int) cnfparamvals[i].val.d.n;
+ setParserEscapeControlCharacterTab(NULL, tmp);
+ } else if(!strcmp(paramblk.descr[i].name, "parser.escapecontrolcharacterscstyle")) {
+ const int tmp = (int) cnfparamvals[i].val.d.n;
+ SetParserEscapeControlCharactersCStyle(tmp);
+ } else if(!strcmp(paramblk.descr[i].name, "parser.parsehostnameandtag")) {
+ const int tmp = (int) cnfparamvals[i].val.d.n;
+ SetParseHOSTNAMEandTAG(tmp);
+ } else if(!strcmp(paramblk.descr[i].name, "parser.permitslashinprogramname")) {
+ loadConf->globals.parser.bPermitSlashInProgramname = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "debug.logfile")) {
+ if(pszAltDbgFileName == NULL) {
+ pszAltDbgFileName = es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ /* can actually happen if debug system also opened altdbg */
+ if(altdbg != -1) {
+ close(altdbg);
+ }
+ if((altdbg = open(pszAltDbgFileName, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY
+ |O_CLOEXEC, S_IRUSR|S_IWUSR)) == -1) {
+ LogError(0, RS_RET_ERR, "debug log file '%s' could not be opened",
+ pszAltDbgFileName);
+ }
+ }
+ LogError(0, RS_RET_OK, "debug log file is '%s', fd %d", pszAltDbgFileName, altdbg);
+ } else if(!strcmp(paramblk.descr[i].name, "janitor.interval")) {
+ loadConf->globals.janitorInterval = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "net.ipprotocol")) {
+ char *proto = es_str2cstr(cnfparamvals[i].val.d.estr, NULL);
+ if(!strcmp(proto, "unspecified")) {
+ loadConf->globals.iDefPFFamily = PF_UNSPEC;
+ } else if(!strcmp(proto, "ipv4-only")) {
+ loadConf->globals.iDefPFFamily = PF_INET;
+ } else if(!strcmp(proto, "ipv6-only")) {
+ loadConf->globals.iDefPFFamily = PF_INET6;
+ } else{
+ LogError(0, RS_RET_ERR, "invalid net.ipprotocol "
+ "parameter '%s' -- ignored", proto);
+ }
+ free(proto);
+ } else if(!strcmp(paramblk.descr[i].name, "senders.reportnew")) {
+ loadConf->globals.reportNewSenders = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "senders.reportgoneaway")) {
+ loadConf->globals.reportGoneAwaySenders = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "senders.timeoutafter")) {
+ loadConf->globals.senderStatsTimeout = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "senders.keeptrack")) {
+ loadConf->globals.senderKeepTrack = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "inputs.timeout.shutdown")) {
+ loadConf->globals.inputTimeoutShutdown = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "privdrop.group.keepsupplemental")) {
+ loadConf->globals.gidDropPrivKeepSupplemental = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "privdrop.group.id")) {
+ loadConf->globals.gidDropPriv = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "privdrop.group.name")) {
+ loadConf->globals.gidDropPriv = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "privdrop.user.id")) {
+ loadConf->globals.uidDropPriv = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "privdrop.user.name")) {
+ loadConf->globals.uidDropPriv = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "security.abortonidresolutionfail")) {
+ loadConf->globals.abortOnIDResolutionFail = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "net.acladdhostnameonfail")) {
+ loadConf->globals.ACLAddHostnameOnFail = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "net.aclresolvehostname")) {
+ loadConf->globals.ACLDontResolve = !((int) cnfparamvals[i].val.d.n);
+ } else if(!strcmp(paramblk.descr[i].name, "net.enabledns")) {
+ SetDisableDNS(!((int) cnfparamvals[i].val.d.n));
+ } else if(!strcmp(paramblk.descr[i].name, "net.permitwarning")) {
+ SetOptionDisallowWarning(!((int) cnfparamvals[i].val.d.n));
+ } else if(!strcmp(paramblk.descr[i].name, "abortonuncleanconfig")) {
+ loadConf->globals.bAbortOnUncleanConfig = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "abortonfailedqueuestartup")) {
+ loadConf->globals.bAbortOnFailedQueueStartup = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "internalmsg.ratelimit.burst")) {
+ loadConf->globals.intMsgRateLimitBurst = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "internalmsg.ratelimit.interval")) {
+ loadConf->globals.intMsgRateLimitItv = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "internalmsg.severity")) {
+ loadConf->globals.intMsgsSeverityFilter = (int) cnfparamvals[i].val.d.n;
+ if((loadConf->globals.intMsgsSeverityFilter < 0) ||
+ (loadConf->globals.intMsgsSeverityFilter > 7)) {
+ parser_errmsg("invalid internalmsg.severity value");
+ loadConf->globals.intMsgsSeverityFilter = DFLT_INT_MSGS_SEV_FILTER;
+ }
+ } else if(!strcmp(paramblk.descr[i].name, "environment")) {
+ for(int j = 0 ; j < cnfparamvals[i].val.d.ar->nmemb ; ++j) {
+ char *const var = es_str2cstr(cnfparamvals[i].val.d.ar->arr[j], NULL);
+ do_setenv(var);
+ free(var);
+ }
+ } else if(!strcmp(paramblk.descr[i].name, "errormessagestostderr.maxnumber")) {
+ loadConf->globals.maxErrMsgToStderr = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "debug.files")) {
+ free(glblDbgFiles); /* "fix" Coverity false positive */
+ glblDbgFilesNum = cnfparamvals[i].val.d.ar->nmemb;
+ glblDbgFiles = (char**) malloc(cnfparamvals[i].val.d.ar->nmemb * sizeof(char*));
+ for(int j = 0 ; j < cnfparamvals[i].val.d.ar->nmemb ; ++j) {
+ glblDbgFiles[j] = es_str2cstr(cnfparamvals[i].val.d.ar->arr[j], NULL);
+ }
+ qsort(glblDbgFiles, glblDbgFilesNum, sizeof(char*), qs_arrcmp_glblDbgFiles);
+ } else if(!strcmp(paramblk.descr[i].name, "debug.whitelist")) {
+ glblDbgWhitelist = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "shutdown.queue.doublesize")) {
+ loadConf->globals.shutdownQueueDoubleSize = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "umask")) {
+ loadConf->globals.umask = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "shutdown.enable.ctlc")) {
+ loadConf->globals.permitCtlC = (int) cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "default.action.queue.timeoutshutdown")) {
+ loadConf->globals.actq_dflt_toQShutdown = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "default.action.queue.timeoutactioncompletion")) {
+ loadConf->globals.actq_dflt_toActShutdown = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "default.action.queue.timeoutenqueue")) {
+ loadConf->globals.actq_dflt_toEnq = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "default.action.queue.timeoutworkerthreadshutdown")) {
+ loadConf->globals.actq_dflt_toWrkShutdown = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "default.ruleset.queue.timeoutshutdown")) {
+ loadConf->globals.ruleset_dflt_toQShutdown = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "default.ruleset.queue.timeoutactioncompletion")) {
+ loadConf->globals.ruleset_dflt_toActShutdown = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "default.ruleset.queue.timeoutenqueue")) {
+ loadConf->globals.ruleset_dflt_toEnq = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "default.ruleset.queue.timeoutworkerthreadshutdown")) {
+ loadConf->globals.ruleset_dflt_toWrkShutdown = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "reverselookup.cache.ttl.default")) {
+ loadConf->globals.dnscacheDefaultTTL = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "reverselookup.cache.ttl.enable")) {
+ loadConf->globals.dnscacheEnableTTL = cnfparamvals[i].val.d.n;
+ } else if(!strcmp(paramblk.descr[i].name, "parser.supportcompressionextension")) {
+ loadConf->globals.bSupportCompressionExtension = cnfparamvals[i].val.d.n;
+ } else {
+ dbgprintf("glblDoneLoadCnf: program error, non-handled "
+ "param '%s'\n", paramblk.descr[i].name);
+ }
+ }
+
+ if(loadConf->globals.debugOnShutdown && Debug != DEBUG_FULL) {
+ Debug = DEBUG_ONDEMAND;
+ stddbg = -1;
+ }
+
+finalize_it:
+ /* we have now read the config. We need to query the local host name now
+ * as it was set by the config.
+ *
+ * Note: early messages are already emited, and have "[localhost]" as
+ * hostname. These messages are currently in iminternal queue. Once they
+ * are taken from that queue, the hostname will be adapted.
+ */
+ queryLocalHostname(loadConf);
+ RETiRet;
+}
+
+
+/* Initialize the glbl class. Must be called as the very first method
+ * before anything else is called inside this class.
+ * rgerhards, 2008-02-19
+ */
+BEGINAbstractObjClassInit(glbl, 1, OBJ_IS_CORE_MODULE) /* class, version */
+ /* request objects we use */
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+
+ /* intialize properties */
+ storeLocalHostIPIF((uchar*)"127.0.0.1");
+
+ /* config handlers are never unregistered and need not be - we are always loaded ;) */
+ CHKiRet(regCfSysLineHdlr((uchar *)"debugfile", 0, eCmdHdlrGetWord, setDebugFile, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"debuglevel", 0, eCmdHdlrInt, setDebugLevel, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"workdirectory", 0, eCmdHdlrGetWord, setWorkDir, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"dropmsgswithmaliciousdnsptrrecords", 0, eCmdHdlrBinary, SetDropMalPTRMsgs,
+ NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriver", 0, eCmdHdlrGetWord, setDfltNetstrmDrvr, NULL,
+ NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercafile", 0, eCmdHdlrGetWord,
+ setDfltNetstrmDrvrCAF, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercrlfile", 0, eCmdHdlrGetWord,
+ setDfltNetstrmDrvrCRLF, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriverkeyfile", 0, eCmdHdlrGetWord,
+ setDfltNetstrmDrvrKeyFile, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercertfile", 0, eCmdHdlrGetWord,
+ setDfltNetstrmDrvrCertFile, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"localhostname", 0, eCmdHdlrGetWord, NULL, &LocalHostNameOverride, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"localhostipif", 0, eCmdHdlrGetWord, setLocalHostIPIF, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"netstreamdrivercaextrafiles", 0, eCmdHdlrGetWord, setNetstrmDrvrCAExtraFiles,
+ NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"optimizeforuniprocessor", 0, eCmdHdlrGoneAway, NULL, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"preservefqdn", 0, eCmdHdlrBinary, NULL, &bPreserveFQDN, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"maxmessagesize", 0, eCmdHdlrSize, legacySetMaxMessageSize, NULL, NULL));
+
+ /* Deprecated parser config options */
+ CHKiRet(regCfSysLineHdlr((uchar *)"controlcharacterescapeprefix", 0, eCmdHdlrGetChar,
+ setParserControlCharacterEscapePrefix, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"droptrailinglfonreception", 0, eCmdHdlrBinary,
+ setParserDropTrailingLFOnReception, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactersonreceive", 0, eCmdHdlrBinary,
+ setParserEscapeControlCharactersOnReceive, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"spacelfonreceive", 0, eCmdHdlrBinary,
+ setParserSpaceLFOnReceive, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"escape8bitcharactersonreceive", 0, eCmdHdlrBinary,
+ setParserEscape8BitCharactersOnReceive, NULL, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactertab", 0, eCmdHdlrBinary,
+ setParserEscapeControlCharacterTab, NULL, NULL));
+
+ CHKiRet(regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, NULL));
+
+ INIT_ATOMIC_HELPER_MUT(mutTerminateInputs);
+ENDObjClassInit(glbl)
+
+
+/* Exit the glbl class.
+ * rgerhards, 2008-04-17
+ */
+BEGINObjClassExit(glbl, OBJ_IS_CORE_MODULE) /* class, version */
+ free(LocalDomain);
+ free(LocalHostName);
+ free(LocalHostNameOverride);
+ free(LocalFQDNName);
+ objRelease(prop, CORE_COMPONENT);
+ if(propLocalHostNameToDelete != NULL)
+ prop.Destruct(&propLocalHostNameToDelete);
+ DESTROY_ATOMIC_HELPER_MUT(mutTerminateInputs);
+ENDObjClassExit(glbl)