summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog153
-rw-r--r--Makefile.am6
-rw-r--r--Makefile.in7
-rw-r--r--action.c32
-rw-r--r--action.h4
-rw-r--r--conf.c14
-rw-r--r--config.h.in9
-rwxr-xr-xconfigure261
-rw-r--r--configure.ac50
-rw-r--r--doc/Makefile.am10
-rw-r--r--doc/Makefile.in10
-rw-r--r--doc/features.html10
-rw-r--r--doc/gssapi.html118
-rw-r--r--doc/imgssapi.html6
-rw-r--r--doc/imklog.html74
-rw-r--r--doc/imrelp.html52
-rw-r--r--doc/imuxsock.html47
-rw-r--r--doc/licensing.html72
-rw-r--r--doc/manual.html24
-rw-r--r--doc/ommail.html128
-rw-r--r--doc/omrelp.html54
-rw-r--r--doc/property_replacer.html88
-rw-r--r--doc/queues.html12
-rw-r--r--doc/rscript_abnf.html4
-rw-r--r--doc/rsyslog_conf.html86
-rw-r--r--doc/rsyslog_ng_comparison.html24
-rw-r--r--doc/rsyslog_packages.html83
-rw-r--r--doc/rsyslog_reliable_forwarding.html152
-rw-r--r--doc/status.html53
-rw-r--r--doc/troubleshoot.html35
-rw-r--r--expr.c4
-rw-r--r--glbl.h1
-rw-r--r--modules.c14
-rw-r--r--msg.c115
-rw-r--r--net.c47
-rw-r--r--net.h5
-rw-r--r--obj-types.h2
-rw-r--r--obj.c10
-rw-r--r--obj.h4
-rw-r--r--omfwd.c39
-rw-r--r--omusrmsg.c6
-rw-r--r--outchannel.c51
-rw-r--r--parse.c58
-rw-r--r--parse.h2
-rw-r--r--plugins/imfile/imfile.c5
-rw-r--r--plugins/imklog/Makefile.am12
-rw-r--r--plugins/imklog/Makefile.in34
-rw-r--r--plugins/imklog/bsd.c181
-rw-r--r--plugins/imklog/imklog.c683
-rw-r--r--plugins/imklog/imklog.h32
-rw-r--r--plugins/imklog/ksym.c113
-rw-r--r--plugins/imklog/ksym_mod.c12
-rw-r--r--plugins/imklog/linux.c544
-rw-r--r--plugins/immark/immark.c2
-rw-r--r--plugins/imuxsock/imuxsock.c2
-rw-r--r--plugins/omgssapi/omgssapi.c38
-rw-r--r--plugins/ommail/Makefile.am6
-rw-r--r--plugins/ommail/Makefile.in494
-rw-r--r--plugins/ommail/ommail.c630
-rw-r--r--plugins/omrelp/omrelp.c12
-rw-r--r--queue.c113
-rw-r--r--queue.h15
-rw-r--r--rsyslog.conf5
-rw-r--r--rsyslog.conf.512
-rw-r--r--rsyslog.h5
-rw-r--r--rsyslogd.86
-rw-r--r--stringbuf.h1
-rw-r--r--syslogd.c368
-rw-r--r--syslogd.h3
-rw-r--r--tcpsrv.c28
-rw-r--r--template.c63
-rw-r--r--template.h3
-rw-r--r--wti.c8
-rw-r--r--wtp.c1
-rw-r--r--wtp.h2
75 files changed, 4299 insertions, 1170 deletions
diff --git a/ChangeLog b/ChangeLog
index 831f5aa..2bb38fe 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,126 @@
---------------------------------------------------------------------------
+Version 3.18.1 (rgerhards), 2008-07-21
+- bugfix: potential segfault in creating message mutex in non-direct queue
+ mode. rsyslogd segfaults on freeeBSD 7.0 (an potentially other platforms)
+ if an action queue is running in any other mode than non-direct. The
+ same problem can potentially be triggered by some main message queue
+ settings. In any case, it will manifest during rsylog's startup. It is
+ unlikely to happen after a successful startup (the only window of
+ exposure may be a relatively seldom executed action running in queued
+ mode). This has been corrected. Thank to HKS for point out the problem.
+- bugfix: priority was incorrectly calculated on FreeBSD 7,
+ because the LOG_MAKEPRI() C macro has a different meaning there (it
+ is just a simple addition of faciltity and severity). I have changed
+ this to use own, consistent, code for PRI calculation. [Backport from
+ 3.19.10]
+- bugfix: remove PRI part from kernel message if it is present
+ Thanks to Michael Biebl for reporting this bug
+- bugfix: mark messages were not correctly written to text log files
+ the markmessageinterval was not correctly propagated to all places
+ where it was needed. This resulted in rsyslog using the default
+ (20 minutes) in some code pathes, what looked to the user like mark
+ messages were never written.
+- added a new property replacer option "sp-if-no-1st-sp" to cover
+ a problem with RFC 3164 based interpreation of tag separation. While
+ it is a generic approach, it fixes a format problem introduced in
+ 3.18.0, where kernel messages no longer had a space after the tag.
+ This is done by a modifcation of the default templates.
+ Please note that this may affect some messages where there intentionally
+ is no space between the tag and the first character of the message
+ content. If so, this needs to be worked around via a specific
+ template. However, we consider this scenario to be quite remote and,
+ even if it exists, it is not expected that it will actually cause
+ problems with log parsers (instead, we assume the new default template
+ behaviour may fix previous problems with log parsers due to the
+ missing space).
+- bugfix: imklog module was not correctly compiled for GNU/kFreeBSD.
+ Thanks to Petr Salinger for the patch
+- doc bugfix: property replacer options secpath-replace and
+ secpath-drop were not documented
+- doc bugfix: fixed some typos in rsyslog.conf man page
+- fixed typo in source comment - thanks to Rio Fujita
+- some general cleanup (thanks to Michael Biebl)
+---------------------------------------------------------------------------
+Version 3.18.0 (rgerhards), 2008-07-11
+- begun a new v3-stable based on former 3.17.4 beta plus patches to
+ previous v3-stable
+- bugfix in RainerScript: syntax error was not always detected
+---------------------------------------------------------------------------
+Version 3.17.5 (rgerhards), 2008-06-27
+- added doc: howto set up a reliable connection to remote server via
+ queued mode (and plain tcp protocol)
+- bugfix: comments after actions were not properly treated. For some
+ actions (e.g. forwarding), this could also lead to invalid configuration
+---------------------------------------------------------------------------
+Version 3.17.4 (rgerhards), 2008-06-16
+- changed default for $KlogSymbolLookup to "off". The directive is
+ also scheduled for removal in a later version. This was necessary
+ because on kernels >= 2.6, the kernel does the symbol lookup itself. The
+ imklog lookup logic then breaks the log message and makes it unusable.
+---------------------------------------------------------------------------
+Version 3.17.3 (rgerhards), 2008-05-28
+- bugfix: imklog went into an endless loop if a PRI value was inside
+ a kernel log message (unusual case under Linux, frequent under BSD)
+---------------------------------------------------------------------------
+Version 3.17.2 (rgerhards), 2008-05-04
+- this version is the new beta, based on 3.17.1 devel feature set
+- merged in imklog bug fix from v3-stable (3.16.1)
+---------------------------------------------------------------------------
+Version 3.17.1 (rgerhards), 2008-04-15
+- removed dependency on MAXHOSTNAMELEN as much as it made sense.
+ GNU/Hurd does not define it (because it has no limit), and we have taken
+ care for cases where it is undefined now. However, some very few places
+ remain where IMHO it currently is not worth fixing the code. If it is
+ not defined, we have used a generous value of 1K, which is above IETF
+ RFC's on hostname length at all. The memory consumption is no issue, as
+ there are only a handful of this buffers allocated *per run* -- that's
+ also the main reason why we consider it not worth to be fixed any further.
+- enhanced legacy syslog parser to handle slightly malformed messages
+ (with a space in front of the timestamp) - at least HP procurve is
+ known to do that and I won't outrule that others also do it. The
+ change looks quite unintrusive and so we added it to the parser.
+- implemented klogd functionality for BSD
+- implemented high precision timestamps for the kernel log. Thanks to
+ Michael Biebl for pointing out that the kernel log did not have them.
+- provided ability to discard non-kernel messages if they are present
+ in the kernel log (seems to happen on BSD)
+- implemented $KLogInternalMsgFacility config directive
+- implemented $KLogPermitNonKernelFacility config directive
+Plus a number of bugfixes that were applied to v3-stable and beta
+branches (not mentioned here in detail).
+---------------------------------------------------------------------------
+Version 3.17.0 (rgerhards), 2008-04-08
+- added native ability to send mail messages
+- removed no longer needed file relptuil.c/.h
+- added $ActionExecOnlyOnceEveryInterval config directive
+- bugfix: memory leaks in script engine
+- bugfix: zero-length strings were not supported in object
+ deserializer
+- properties are now case-insensitive everywhere (script, filters,
+ templates)
+- added the capability to specify a processing (actually dequeue)
+ timeframe with queues - so things can be configured to be done
+ at off-peak hours
+- We have removed the 32 character size limit (from RFC3164) on the
+ tag. This had bad effects on existing envrionments, as sysklogd didn't
+ obey it either (probably another bug in RFC3164...). We now receive
+ the full size, but will modify the outputs so that only 32 characters
+ max are used by default. If you need large tags in the output, you need
+ to provide custom templates.
+- changed command line processing. -v, -M, -c options are now parsed
+ and processed before all other options. Inter-option dependencies
+ have been relieved. Among others, permits to specify intial module
+ load path via -M only (not the environment) which makes it much
+ easier to work with non-standard module library locations. Thanks
+ to varmojfekoj for suggesting this change. Matches bugzilla bug 55.
+- bugfix: some messages were emited without hostname
+Plus a number of bugfixes that were applied to v3-stable and beta
+branches (not mentioned here in detail).
+---------------------------------------------------------------------------
+Version 3.16.3 (rgerhards), 2008-07-11
+- updated information on rsyslog packages
+- bugfix: memory leak in disk-based queue modes
+---------------------------------------------------------------------------
Version 3.16.2 (rgerhards), 2008-06-25
- fixed potential segfault due to invalid call to cfsysline
thanks to varmojfekoj for the patch
@@ -486,6 +608,37 @@ Version 2.0.4 STABLE (rgerhards), 2008-03-27
- bugfix: internally generated messages had "FROMHOST" property not set
- bugfix: continue parsing if tag is oversize (discard oversize part) - thanks
to mclaughlin77@gmail.com for the patch
+- added $HHOUR and $QHOUR system properties - can be used for half- and
+ quarter-hour logfile rotation
+---------------------------------------------------------------------------
+Version 2.0.3 STABLE (rgerhards), 2008-03-12
+- bugfix: setting for $EscapeCopntrolCharactersOnReceive was not
+ properly initialized
+- bugfix: resolved potential segfault condition on HUP (extremely
+ unlikely to happen in practice), for details see tracker:
+ http://bugzilla.adiscon.com/show_bug.cgi?id=38
+- improved the man pages a bit - thanks to Michael Biebl for the patch
+- bugfix: not properly initialized data could cause several segfaults if
+ there were errors in the config file - thanks to varmojfekoj for the patch
+---------------------------------------------------------------------------
+Version 2.0.2 STABLE (rgerhards), 2008-02-12
+- fixed a bug that could cause invalid string handling via strerror_r
+ varmojfekoj provided the patch - many thanks!
+- added x-info field to rsyslogd startup/shutdown message. Hopefully
+ points users to right location for further info (many don't even know
+ they run rsyslog ;))
+- bugfix: suspended actions were not always properly resumed
+ varmojfekoj provided the patch - many thanks!
+- bugfix: errno could be changed during mark processing, leading to
+ invalid error messages when processing inputs. Thank to varmojfekoj for
+ pointing out this problem.
+- bugfix: trailing ":" of tag was lost while parsing legacy syslog messages
+ without timestamp - thanks to Anders Blomdell for providing a patch!
+- bugfix (doc): misspelled config directive, invalid signal info
+- applied some doc fixes from Michel Biebl and cleaned up some no longer
+ needed files suggested by him
+- cleaned up stringbuf.c to fix an annoyance reported by Anders Blomdell
+- fixed bug that caused invalid treatment of tabs (HT) in rsyslog.conf
---------------------------------------------------------------------------
Version 2.0.1 STABLE (rgerhards), 2008-01-24
- fixed a bug in integer conversion - but this function was never called,
diff --git a/Makefile.am b/Makefile.am
index 659acfb..0e75710 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -183,7 +183,7 @@ SUBDIRS = . doc
SUBDIRS += plugins/immark plugins/imuxsock plugins/imtcp plugins/imudp plugins/omtesting
-if ENABLE_IMKLOGD
+if ENABLE_IMKLOG
SUBDIRS += plugins/imklog
endif
@@ -218,3 +218,7 @@ endif
if ENABLE_IMFILE
SUBDIRS += plugins/imfile
endif
+
+if ENABLE_MAIL
+SUBDIRS += plugins/ommail
+endif
diff --git a/Makefile.in b/Makefile.in
index 2bc79ee..f5496c7 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -51,7 +51,7 @@ sbin_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2)
# gssapi support
#
@ENABLE_GSSAPI_TRUE@am__append_7 = lmgssutil.la
-@ENABLE_IMKLOGD_TRUE@am__append_8 = plugins/imklog
+@ENABLE_IMKLOG_TRUE@am__append_8 = plugins/imklog
@ENABLE_GSSAPI_TRUE@am__append_9 = plugins/omgssapi plugins/imgssapi
@ENABLE_RELP_TRUE@am__append_10 = plugins/omrelp plugins/imrelp
@ENABLE_MYSQL_TRUE@am__append_11 = plugins/ommysql
@@ -60,6 +60,7 @@ sbin_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2)
@ENABLE_SNMP_TRUE@am__append_14 = plugins/omsnmp
@ENABLE_IMTEMPLATE_TRUE@am__append_15 = plugins/imtemplate
@ENABLE_IMFILE_TRUE@am__append_16 = plugins/imfile
+@ENABLE_MAIL_TRUE@am__append_17 = plugins/ommail
subdir = .
DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in $(srcdir)/config.h.in \
@@ -241,7 +242,7 @@ DIST_SUBDIRS = . doc plugins/immark plugins/imuxsock plugins/imtcp \
plugins/omgssapi plugins/imgssapi plugins/omrelp \
plugins/imrelp plugins/ommysql plugins/omlibdbi \
plugins/ompgsql plugins/omsnmp plugins/imtemplate \
- plugins/imfile
+ plugins/imfile plugins/ommail
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
@@ -531,7 +532,7 @@ SUBDIRS = . doc plugins/immark plugins/imuxsock plugins/imtcp \
plugins/imudp plugins/omtesting $(am__append_8) \
$(am__append_9) $(am__append_10) $(am__append_11) \
$(am__append_12) $(am__append_13) $(am__append_14) \
- $(am__append_15) $(am__append_16)
+ $(am__append_15) $(am__append_16) $(am__append_17)
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-recursive
diff --git a/action.c b/action.c
index 99ae8b3..39c37b5 100644
--- a/action.c
+++ b/action.c
@@ -74,8 +74,10 @@ static int iActionQtoEnq = 2000; /* timeout for queue enque */
static int iActionQtoWrkShutdown = 60000; /* timeout for worker thread shutdown */
static int iActionQWrkMinMsgs = 100; /* minimum messages per worker needed to start a new one */
static int bActionQSaveOnShutdown = 1; /* save queue on shutdown (when DA enabled)? */
-static int iActionQueueDeqSlowdown = 0; /* dequeue slowdown (simple rate limiting) */
static int64 iActionQueMaxDiskSpace = 0; /* max disk space allocated 0 ==> unlimited */
+static int iActionQueueDeqSlowdown = 0; /* dequeue slowdown (simple rate limiting) */
+static int iActionQueueDeqtWinFromHr = 0; /* hour begin of time frame when queue is to be dequeued */
+static int iActionQueueDeqtWinToHr = 25; /* hour begin of time frame when queue is to be dequeued */
/* the counter below counts actions created. It is used to obtain unique IDs for the action. They
* should not be relied on for any long-term activity (e.g. disk queue names!), but they are nice
@@ -113,8 +115,10 @@ actionResetQueueParams(void)
iActionQtoWrkShutdown = 60000; /* timeout for worker thread shutdown */
iActionQWrkMinMsgs = 100; /* minimum messages per worker needed to start a new one */
bActionQSaveOnShutdown = 1; /* save queue on shutdown (when DA enabled)? */
- iActionQueueDeqSlowdown = 0;
iActionQueMaxDiskSpace = 0;
+ iActionQueueDeqSlowdown = 0;
+ iActionQueueDeqtWinFromHr = 0;
+ iActionQueueDeqtWinToHr = 25; /* 25 disables time windowed dequeuing */
glbliActionResumeRetryCount = 0; /* I guess it is smart to reset this one, too */
@@ -237,7 +241,9 @@ actionConstructFinalize(action_t *pThis)
setQPROP(queueSetiDiscardSeverity, "$ActionQueueDiscardSeverity", iActionQDiscardSeverity);
setQPROP(queueSetiMinMsgsPerWrkr, "$ActionQueueWorkerThreadMinimumMessages", iActionQWrkMinMsgs);
setQPROP(queueSetbSaveOnShutdown, "$ActionQueueSaveOnShutdown", bActionQSaveOnShutdown);
- setQPROP(queueSetiDeqSlowdown, "$ActionQueueDequeueSlowdown", iActionQueueDeqSlowdown);
+ setQPROP(queueSetiDeqSlowdown, "$ActionQueueDequeueSlowdown", iActionQueueDeqSlowdown);
+ setQPROP(queueSetiDeqtWinFromHr, "$ActionQueueDequeueTimeBegin", iActionQueueDeqtWinFromHr);
+ setQPROP(queueSetiDeqtWinToHr, "$ActionQueueDequeueTimeEnd", iActionQueueDeqtWinToHr);
# undef setQPROP
# undef setQPROPstr
@@ -498,6 +504,7 @@ actionWriteToAction(action_t *pAction)
{
msg_t *pMsgSave; /* to save current message pointer, necessary to restore
it in case it needs to be updated (e.g. repeated msgs) */
+ time_t now;
DEFiRet;
pMsgSave = NULL; /* indicate message poiner not saved */
@@ -536,7 +543,20 @@ actionWriteToAction(action_t *pAction)
dbgprintf("Called action, logging to %s", module.GetStateName(pAction->pMod));
- time(&pAction->f_time); /* we need this for message repeation processing */
+ time(&now); /* we need this for message repeation processing AND $ActionExecOnlyOnceEveryInterval */
+ /* now check if we need to drop the message because otherwise the action would be too
+ * frequently called. -- rgerhards, 2008-04-08
+ */
+ if(pAction->f_time != 0 && pAction->iSecsExecOnceInterval + pAction->tLastExec > now) {
+ /* in this case we need to discard the message - its not yet time to exec the action */
+ dbgprintf("action not yet ready again to be executed, onceInterval %d, tCurr %d, tNext %d\n",
+ (int) pAction->iSecsExecOnceInterval, (int) now,
+ (int) (pAction->iSecsExecOnceInterval + pAction->tLastExec));
+ FINALIZE;
+ }
+
+ pAction->tLastExec = now; /* we need this OnceInterval */
+ pAction->f_time = now; /* we need this for message repeation processing */
/* When we reach this point, we have a valid, non-disabled action.
* So let's enqueue our message for execution. -- rgerhards, 2007-07-24
@@ -680,6 +700,8 @@ actionAddCfSysLineHdrl(void)
CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuemaxfilesize", 0, eCmdHdlrSize, NULL, &iActionQueMaxFileSize, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuesaveonshutdown", 0, eCmdHdlrBinary, NULL, &bActionQSaveOnShutdown, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuedequeueslowdown", 0, eCmdHdlrInt, NULL, &iActionQueueDeqSlowdown, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuedequeuetimebegin", 0, eCmdHdlrInt, NULL, &iActionQueueDeqtWinFromHr, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuedequeuetimeend", 0, eCmdHdlrInt, NULL, &iActionQueueDeqtWinToHr, NULL));
finalize_it:
RETiRet;
@@ -710,6 +732,7 @@ addAction(action_t **ppAction, modInfo_t *pMod, void *pModData, omodStringReques
pAction->pMod = pMod;
pAction->pModData = pModData;
pAction->bExecWhenPrevSusp = bActExecWhenPrevSusp;
+ pAction->iSecsExecOnceInterval = iActExecOnceInterval;
/* check if we can obtain the template pointers - TODO: move to separate function? */
pAction->iNumTpls = OMSRgetEntryCount(pOMSR);
@@ -800,6 +823,5 @@ finalize_it:
RETiRet;
}
-
/* vi:set ai:
*/
diff --git a/action.h b/action.h
index 1fa05c1..99108aa 100644
--- a/action.h
+++ b/action.h
@@ -39,8 +39,10 @@ extern int glbliActionResumeRetryCount;
/* the following struct defines the action object data structure
*/
struct action_s {
- time_t f_time; /* time this was last written */
+ time_t f_time; /* used for "message repeated n times" - be careful, old, old code */
+ time_t tLastExec; /* time this action was last executed */
int bExecWhenPrevSusp;/* execute only when previous action is suspended? */
+ int iSecsExecOnceInterval; /* if non-zero, minimum seconds to wait until action is executed again */
short bEnabled; /* is the related action enabled (1) or disabled (0)? */
short bSuspended; /* is the related action temporarily suspended? */
time_t ttResumeRtry; /* when is it time to retry the resume? */
diff --git a/conf.c b/conf.c
index 5f0dca0..5a53480 100644
--- a/conf.c
+++ b/conf.c
@@ -473,28 +473,26 @@ rsRetVal cflineParseTemplateName(uchar** pp, omodStringRequest_t *pOMSR, int iEn
{
uchar *p;
uchar *tplName;
- DEFiRet;
cstr_t *pStrB;
+ DEFiRet;
ASSERT(pp != NULL);
ASSERT(*pp != NULL);
ASSERT(pOMSR != NULL);
p =*pp;
- /* a template must follow - search it and complain, if not found
- */
+ /* a template must follow - search it and complain, if not found */
skipWhiteSpace(&p);
if(*p == ';')
++p; /* eat it */
else if(*p != '\0' && *p != '#') {
errmsg.LogError(NO_ERRCODE, "invalid character in selector line - ';template' expected");
- iRet = RS_RET_ERR;
- goto finalize_it;
+ ABORT_FINALIZE(RS_RET_ERR);
}
skipWhiteSpace(&p); /* go to begin of template name */
- if(*p == '\0') {
+ if(*p == '\0' || *p == '#') {
/* no template specified, use the default */
/* TODO: check NULL ptr */
tplName = (uchar*) strdup((char*)dfltTplName);
@@ -817,7 +815,7 @@ static rsRetVal cflineProcessPropFilter(uchar **pline, register selector_t *f)
}
/* read property */
- iRet = parsDelimCStr(pPars, &f->f_filterData.prop.pCSPropName, ',', 1, 1);
+ iRet = parsDelimCStr(pPars, &f->f_filterData.prop.pCSPropName, ',', 1, 1, 1);
if(iRet != RS_RET_OK) {
errmsg.LogError(NO_ERRCODE, "error %d parsing filter property - ignoring selector", iRet);
rsParsDestruct(pPars);
@@ -825,7 +823,7 @@ static rsRetVal cflineProcessPropFilter(uchar **pline, register selector_t *f)
}
/* read operation */
- iRet = parsDelimCStr(pPars, &pCSCompOp, ',', 1, 1);
+ iRet = parsDelimCStr(pPars, &pCSCompOp, ',', 1, 1, 1);
if(iRet != RS_RET_OK) {
errmsg.LogError(NO_ERRCODE, "error %d compare operation property - ignoring selector", iRet);
rsParsDestruct(pPars);
diff --git a/config.h.in b/config.h.in
index 9dfb954..d868c36 100644
--- a/config.h.in
+++ b/config.h.in
@@ -1,8 +1,5 @@
/* config.h.in. Generated from configure.ac by autoheader. */
-/* Description */
-#undef BSD
-
/* Defined if debug mode is enabled (its easier to check). */
#undef DEBUG
@@ -248,6 +245,9 @@
slash. */
#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
+/* Define with a value if your <sys/param.h> does not define MAXHOSTNAMELEN */
+#undef MAXHOSTNAMELEN
+
/* Defined if debug mode is disabled. */
#undef NDEBUG
@@ -257,6 +257,9 @@
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
#undef NO_MINUS_C_MINUS_O
+/* Indicator for a BSD OS */
+#undef OS_BSD
+
/* Name of package */
#undef PACKAGE
diff --git a/configure b/configure
index aacf822..520e60e 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61 for rsyslog 3.16.2.
+# Generated by GNU Autoconf 2.61 for rsyslog 3.18.1.
#
# Report bugs to <rsyslog@lists.adiscon.com>.
#
@@ -728,8 +728,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='rsyslog'
PACKAGE_TARNAME='rsyslog'
-PACKAGE_VERSION='3.16.2'
-PACKAGE_STRING='rsyslog 3.16.2'
+PACKAGE_VERSION='3.18.1'
+PACKAGE_STRING='rsyslog 3.18.1'
PACKAGE_BUGREPORT='rsyslog@lists.adiscon.com'
ac_unique_file="syslogd.c"
@@ -882,8 +882,12 @@ ENABLE_GSSAPI_TRUE
ENABLE_GSSAPI_FALSE
pthreads_libs
pthreads_cflags
-ENABLE_IMKLOGD_TRUE
-ENABLE_IMKLOGD_FALSE
+ENABLE_IMKLOG_TRUE
+ENABLE_IMKLOG_FALSE
+ENABLE_IMKLOG_BSD_TRUE
+ENABLE_IMKLOG_BSD_FALSE
+ENABLE_IMKLOG_LINUX_TRUE
+ENABLE_IMKLOG_LINUX_FALSE
ENABLE_INET_TRUE
ENABLE_INET_FALSE
HAVE_MYSQL_CONFIG
@@ -906,6 +910,8 @@ snmp_cflags
snmp_libs
ENABLE_RSYSLOGD_TRUE
ENABLE_RSYSLOGD_FALSE
+ENABLE_MAIL_TRUE
+ENABLE_MAIL_FALSE
PKG_CONFIG
RELP_CFLAGS
RELP_LIBS
@@ -1441,7 +1447,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures rsyslog 3.16.2 to adapt to many kinds of systems.
+\`configure' configures rsyslog 3.18.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1511,7 +1517,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of rsyslog 3.16.2:";;
+ short | recursive ) echo "Configuration of rsyslog 3.18.1:";;
esac
cat <<\_ACEOF
@@ -1542,6 +1548,7 @@ Optional Features:
--enable-libdbi Enable libdbi database support [default=no]
--enable-snmp Enable SNMP support [default=no]
--enable-rsyslogd Build rsyslogd [default=yes]
+ --enable-mail Enable mail support [default=no]
--enable-relp Enable RELP support [default=no]
--enable-rfc3195 Enable RFC3195 support [default=no]
--enable-imfile file input module enabled [default=no]
@@ -1637,7 +1644,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-rsyslog configure 3.16.2
+rsyslog configure 3.18.1
generated by GNU Autoconf 2.61
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1651,7 +1658,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by rsyslog $as_me 3.16.2, which was
+It was created by rsyslog $as_me 3.18.1, which was
generated by GNU Autoconf 2.61. Invocation command line was
$ $0 $@
@@ -2341,7 +2348,7 @@ fi
# Define the identity of the package.
PACKAGE='rsyslog'
- VERSION='3.16.2'
+ VERSION='3.18.1'
cat >>confdefs.h <<_ACEOF
@@ -4526,7 +4533,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 4529 "configure"' > conftest.$ac_ext
+ echo '#line 4536 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -7269,11 +7276,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7272: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7279: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7276: \$? = $ac_status" >&5
+ echo "$as_me:7283: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7559,11 +7566,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7562: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7569: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7566: \$? = $ac_status" >&5
+ echo "$as_me:7573: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7663,11 +7670,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7666: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7673: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7670: \$? = $ac_status" >&5
+ echo "$as_me:7677: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -10014,7 +10021,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 10017 "configure"
+#line 10024 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10114,7 +10121,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 10117 "configure"
+#line 10124 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -12534,11 +12541,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:12537: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:12544: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:12541: \$? = $ac_status" >&5
+ echo "$as_me:12548: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -12638,11 +12645,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:12641: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:12648: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:12645: \$? = $ac_status" >&5
+ echo "$as_me:12652: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -14202,11 +14209,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:14205: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:14212: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:14209: \$? = $ac_status" >&5
+ echo "$as_me:14216: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -14306,11 +14313,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:14309: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:14316: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:14313: \$? = $ac_status" >&5
+ echo "$as_me:14320: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -16495,11 +16502,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:16498: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:16505: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:16502: \$? = $ac_status" >&5
+ echo "$as_me:16509: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -16785,11 +16792,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:16788: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:16795: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:16792: \$? = $ac_status" >&5
+ echo "$as_me:16799: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -16889,11 +16896,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:16892: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:16899: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:16896: \$? = $ac_status" >&5
+ echo "$as_me:16903: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -19583,13 +19590,20 @@ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
case "${host}" in
*-*-linux*)
+ os_type="linux"
;;
*-*-*darwin*|*-*-freebsd*|*-*-netbsd*|*-*-openbsd*)
cat >>confdefs.h <<\_ACEOF
-#define BSD 1
+#define OS_BSD 1
_ACEOF
+ os_type="bsd"
+ ;;
+ *-*-kfreebsd*)
+ # kernel is FreeBSD, but userspace is glibc - i.e. like linux
+ # do not DEFINE OS_BSD
+ os_type="bsd"
;;
esac
@@ -23442,6 +23456,67 @@ fi
done
+# Check for MAXHOSTNAMELEN
+{ echo "$as_me:$LINENO: checking for MAXHOSTNAMELEN" >&5
+echo $ECHO_N "checking for MAXHOSTNAMELEN... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+ #include <sys/param.h>
+
+int
+main ()
+{
+
+ return MAXHOSTNAMELEN;
+
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # note: we use 1024 here, which should be far more than needed by any system. If that's too low, we simply
+ # life with the need to change it. Most of the code doesn't need it anyways, but there are a few places
+ # where it actually is needed and it makes no sense to change them.
+
+cat >>confdefs.h <<\_ACEOF
+#define MAXHOSTNAMELEN 1024
+_ACEOF
+
+ { echo "$as_me:$LINENO: result: no; defined as 64" >&5
+echo "${ECHO_T}no; defined as 64" >&6; }
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
# Large file support
# Check whether --enable-largefile was given.
@@ -24238,11 +24313,27 @@ else
fi
if test x$enable_klog = xyes; then
- ENABLE_IMKLOGD_TRUE=
- ENABLE_IMKLOGD_FALSE='#'
+ ENABLE_IMKLOG_TRUE=
+ ENABLE_IMKLOG_FALSE='#'
+else
+ ENABLE_IMKLOG_TRUE='#'
+ ENABLE_IMKLOG_FALSE=
+fi
+
+ if test x$os_type = xbsd; then
+ ENABLE_IMKLOG_BSD_TRUE=
+ ENABLE_IMKLOG_BSD_FALSE='#'
+else
+ ENABLE_IMKLOG_BSD_TRUE='#'
+ ENABLE_IMKLOG_BSD_FALSE=
+fi
+
+ if test x$os_type = xlinux; then
+ ENABLE_IMKLOG_LINUX_TRUE=
+ ENABLE_IMKLOG_LINUX_FALSE='#'
else
- ENABLE_IMKLOGD_TRUE='#'
- ENABLE_IMKLOGD_FALSE=
+ ENABLE_IMKLOG_LINUX_TRUE='#'
+ ENABLE_IMKLOG_LINUX_FALSE=
fi
@@ -25477,6 +25568,31 @@ fi
+# Mail support (so far we do not need a library, but we need to turn this on and off)
+# Check whether --enable-mail was given.
+if test "${enable_mail+set}" = set; then
+ enableval=$enable_mail; case "${enableval}" in
+ yes) enable_mail="yes" ;;
+ no) enable_mail="no" ;;
+ *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-mail" >&5
+echo "$as_me: error: bad value ${enableval} for --enable-mail" >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
+else
+ enable_mail=no
+
+fi
+
+ if test x$enable_mail = xyes; then
+ ENABLE_MAIL_TRUE=
+ ENABLE_MAIL_FALSE='#'
+else
+ ENABLE_MAIL_TRUE='#'
+ ENABLE_MAIL_FALSE=
+fi
+
+
+
# RELP support
# Check whether --enable-relp was given.
if test "${enable_relp+set}" = set; then
@@ -25622,12 +25738,12 @@ if test -n "$RELP_CFLAGS"; then
pkg_cv_RELP_CFLAGS="$RELP_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
- { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"relp\"") >&5
- ($PKG_CONFIG --exists --print-errors "relp") 2>&5
+ { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"relp >= 0.1.1\"") >&5
+ ($PKG_CONFIG --exists --print-errors "relp >= 0.1.1") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; then
- pkg_cv_RELP_CFLAGS=`$PKG_CONFIG --cflags "relp" 2>/dev/null`
+ pkg_cv_RELP_CFLAGS=`$PKG_CONFIG --cflags "relp >= 0.1.1" 2>/dev/null`
else
pkg_failed=yes
fi
@@ -25638,12 +25754,12 @@ if test -n "$RELP_LIBS"; then
pkg_cv_RELP_LIBS="$RELP_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
- { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"relp\"") >&5
- ($PKG_CONFIG --exists --print-errors "relp") 2>&5
+ { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"relp >= 0.1.1\"") >&5
+ ($PKG_CONFIG --exists --print-errors "relp >= 0.1.1") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; then
- pkg_cv_RELP_LIBS=`$PKG_CONFIG --libs "relp" 2>/dev/null`
+ pkg_cv_RELP_LIBS=`$PKG_CONFIG --libs "relp >= 0.1.1" 2>/dev/null`
else
pkg_failed=yes
fi
@@ -25661,14 +25777,14 @@ else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
- RELP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "relp" 2>&1`
+ RELP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "relp >= 0.1.1" 2>&1`
else
- RELP_PKG_ERRORS=`$PKG_CONFIG --print-errors "relp" 2>&1`
+ RELP_PKG_ERRORS=`$PKG_CONFIG --print-errors "relp >= 0.1.1" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$RELP_PKG_ERRORS" >&5
- { { echo "$as_me:$LINENO: error: Package requirements (relp) were not met:
+ { { echo "$as_me:$LINENO: error: Package requirements (relp >= 0.1.1) were not met:
$RELP_PKG_ERRORS
@@ -25679,7 +25795,7 @@ Alternatively, you may set the environment variables RELP_CFLAGS
and RELP_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.
" >&5
-echo "$as_me: error: Package requirements (relp) were not met:
+echo "$as_me: error: Package requirements (relp >= 0.1.1) were not met:
$RELP_PKG_ERRORS
@@ -25996,7 +26112,7 @@ fi
# end of copy template - be sure to serach for imtemplate to find everything!
-ac_config_files="$ac_config_files Makefile doc/Makefile plugins/imudp/Makefile plugins/imtcp/Makefile plugins/imgssapi/Makefile plugins/imuxsock/Makefile plugins/immark/Makefile plugins/imklog/Makefile plugins/imtemplate/Makefile plugins/imfile/Makefile plugins/imrelp/Makefile plugins/omtesting/Makefile plugins/omgssapi/Makefile plugins/ommysql/Makefile plugins/ompgsql/Makefile plugins/omrelp/Makefile plugins/omlibdbi/Makefile plugins/omsnmp/Makefile"
+ac_config_files="$ac_config_files Makefile doc/Makefile plugins/imudp/Makefile plugins/imtcp/Makefile plugins/imgssapi/Makefile plugins/imuxsock/Makefile plugins/immark/Makefile plugins/imklog/Makefile plugins/imtemplate/Makefile plugins/imfile/Makefile plugins/imrelp/Makefile plugins/omtesting/Makefile plugins/omgssapi/Makefile plugins/ommysql/Makefile plugins/ompgsql/Makefile plugins/omrelp/Makefile plugins/omlibdbi/Makefile plugins/ommail/Makefile plugins/omsnmp/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@@ -26129,10 +26245,24 @@ echo "$as_me: error: conditional \"ENABLE_GSSAPI\" was never defined.
Usually this means the macro was only invoked conditionally." >&2;}
{ (exit 1); exit 1; }; }
fi
-if test -z "${ENABLE_IMKLOGD_TRUE}" && test -z "${ENABLE_IMKLOGD_FALSE}"; then
- { { echo "$as_me:$LINENO: error: conditional \"ENABLE_IMKLOGD\" was never defined.
+if test -z "${ENABLE_IMKLOG_TRUE}" && test -z "${ENABLE_IMKLOG_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"ENABLE_IMKLOG\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"ENABLE_IMKLOG\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${ENABLE_IMKLOG_BSD_TRUE}" && test -z "${ENABLE_IMKLOG_BSD_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"ENABLE_IMKLOG_BSD\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"ENABLE_IMKLOG_BSD\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${ENABLE_IMKLOG_LINUX_TRUE}" && test -z "${ENABLE_IMKLOG_LINUX_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"ENABLE_IMKLOG_LINUX\" was never defined.
Usually this means the macro was only invoked conditionally." >&5
-echo "$as_me: error: conditional \"ENABLE_IMKLOGD\" was never defined.
+echo "$as_me: error: conditional \"ENABLE_IMKLOG_LINUX\" was never defined.
Usually this means the macro was only invoked conditionally." >&2;}
{ (exit 1); exit 1; }; }
fi
@@ -26178,6 +26308,13 @@ echo "$as_me: error: conditional \"ENABLE_RSYSLOGD\" was never defined.
Usually this means the macro was only invoked conditionally." >&2;}
{ (exit 1); exit 1; }; }
fi
+if test -z "${ENABLE_MAIL_TRUE}" && test -z "${ENABLE_MAIL_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"ENABLE_MAIL\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"ENABLE_MAIL\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
if test -z "${ENABLE_RELP_TRUE}" && test -z "${ENABLE_RELP_FALSE}"; then
{ { echo "$as_me:$LINENO: error: conditional \"ENABLE_RELP\" was never defined.
Usually this means the macro was only invoked conditionally." >&5
@@ -26513,7 +26650,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by rsyslog $as_me 3.16.2, which was
+This file was extended by rsyslog $as_me 3.18.1, which was
generated by GNU Autoconf 2.61. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -26566,7 +26703,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-rsyslog config.status 3.16.2
+rsyslog config.status 3.18.1
configured by $0, generated by GNU Autoconf 2.61,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
@@ -26699,6 +26836,7 @@ do
"plugins/ompgsql/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/ompgsql/Makefile" ;;
"plugins/omrelp/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/omrelp/Makefile" ;;
"plugins/omlibdbi/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/omlibdbi/Makefile" ;;
+ "plugins/ommail/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/ommail/Makefile" ;;
"plugins/omsnmp/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/omsnmp/Makefile" ;;
*) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
@@ -26916,8 +27054,12 @@ ENABLE_GSSAPI_TRUE!$ENABLE_GSSAPI_TRUE$ac_delim
ENABLE_GSSAPI_FALSE!$ENABLE_GSSAPI_FALSE$ac_delim
pthreads_libs!$pthreads_libs$ac_delim
pthreads_cflags!$pthreads_cflags$ac_delim
-ENABLE_IMKLOGD_TRUE!$ENABLE_IMKLOGD_TRUE$ac_delim
-ENABLE_IMKLOGD_FALSE!$ENABLE_IMKLOGD_FALSE$ac_delim
+ENABLE_IMKLOG_TRUE!$ENABLE_IMKLOG_TRUE$ac_delim
+ENABLE_IMKLOG_FALSE!$ENABLE_IMKLOG_FALSE$ac_delim
+ENABLE_IMKLOG_BSD_TRUE!$ENABLE_IMKLOG_BSD_TRUE$ac_delim
+ENABLE_IMKLOG_BSD_FALSE!$ENABLE_IMKLOG_BSD_FALSE$ac_delim
+ENABLE_IMKLOG_LINUX_TRUE!$ENABLE_IMKLOG_LINUX_TRUE$ac_delim
+ENABLE_IMKLOG_LINUX_FALSE!$ENABLE_IMKLOG_LINUX_FALSE$ac_delim
ENABLE_INET_TRUE!$ENABLE_INET_TRUE$ac_delim
ENABLE_INET_FALSE!$ENABLE_INET_FALSE$ac_delim
HAVE_MYSQL_CONFIG!$HAVE_MYSQL_CONFIG$ac_delim
@@ -26940,6 +27082,8 @@ snmp_cflags!$snmp_cflags$ac_delim
snmp_libs!$snmp_libs$ac_delim
ENABLE_RSYSLOGD_TRUE!$ENABLE_RSYSLOGD_TRUE$ac_delim
ENABLE_RSYSLOGD_FALSE!$ENABLE_RSYSLOGD_FALSE$ac_delim
+ENABLE_MAIL_TRUE!$ENABLE_MAIL_TRUE$ac_delim
+ENABLE_MAIL_FALSE!$ENABLE_MAIL_FALSE$ac_delim
PKG_CONFIG!$PKG_CONFIG$ac_delim
RELP_CFLAGS!$RELP_CFLAGS$ac_delim
RELP_LIBS!$RELP_LIBS$ac_delim
@@ -26956,7 +27100,7 @@ ENABLE_IMTEMPLATE_FALSE!$ENABLE_IMTEMPLATE_FALSE$ac_delim
LTLIBOBJS!$LTLIBOBJS$ac_delim
_ACEOF
- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 54; then
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 60; then
break
elif $ac_last_try; then
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
@@ -27560,13 +27704,14 @@ echo "****************************************************"
echo "rsyslog will be compiled with the following settings:"
echo
echo "Multithreading support enabled: $enable_pthreads"
-echo "Klog functionality enabled: $enable_klog"
+echo "Klog functionality enabled: $enable_klog ($os_type)"
echo "Regular expressions support enabled: $enable_regexp"
echo "Zlib compression support enabled: $enable_zlib"
echo "MySql support enabled: $enable_mysql"
echo "libdbi support enabled: $enable_libdbi"
echo "PostgreSQL support enabled: $enable_pgsql"
echo "SNMP support enabled: $enable_snmp"
+echo "Mail support enabled: $enable_mail"
echo "RELP support enabled: $enable_relp"
echo "file input module enabled: $enable_imfile"
echo "input template module will be compiled: $enable_imtemplate"
diff --git a/configure.ac b/configure.ac
index cac215f..1589ad6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
-AC_INIT([rsyslog],[3.16.2],[rsyslog@lists.adiscon.com])
+AC_INIT([rsyslog],[3.18.1],[rsyslog@lists.adiscon.com])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([syslogd.c])
AC_CONFIG_HEADERS([config.h])
@@ -21,9 +21,16 @@ AC_CANONICAL_HOST
case "${host}" in
*-*-linux*)
+ os_type="linux"
;;
*-*-*darwin*|*-*-freebsd*|*-*-netbsd*|*-*-openbsd*)
- AC_DEFINE([BSD], [1], [Description])
+ AC_DEFINE([OS_BSD], [1], [Indicator for a BSD OS])
+ os_type="bsd"
+ ;;
+ *-*-kfreebsd*)
+ # kernel is FreeBSD, but userspace is glibc - i.e. like linux
+ # do not DEFINE OS_BSD
+ os_type="bsd"
;;
esac
@@ -83,6 +90,22 @@ AC_FUNC_STRERROR_R
AC_FUNC_VPRINTF
AC_CHECK_FUNCS([flock basename alarm clock_gettime gethostbyname gethostname gettimeofday localtime_r memset mkdir regcomp select setid socket strcasecmp strchr strdup strerror strndup strnlen strrchr strstr strtol strtoul uname ttyname_r])
+# Check for MAXHOSTNAMELEN
+AC_MSG_CHECKING(for MAXHOSTNAMELEN)
+AC_TRY_COMPILE([
+ #include <sys/param.h>
+ ], [
+ return MAXHOSTNAMELEN;
+ ]
+ ,
+ AC_MSG_RESULT(yes)
+ ,
+ # note: we use 1024 here, which should be far more than needed by any system. If that's too low, we simply
+ # life with the need to change it. Most of the code doesn't need it anyways, but there are a few places
+ # where it actually is needed and it makes no sense to change them.
+ AC_DEFINE(MAXHOSTNAMELEN, 1024, [Define with a value if your <sys/param.h> does not define MAXHOSTNAMELEN])
+ AC_MSG_RESULT(no; defined as 64)
+)
# Large file support
AC_ARG_ENABLE(largefile,
@@ -202,7 +225,9 @@ AC_ARG_ENABLE(klog,
esac],
[enable_klog="yes"]
)
-AM_CONDITIONAL(ENABLE_IMKLOGD, test x$enable_klog = xyes)
+AM_CONDITIONAL(ENABLE_IMKLOG, test x$enable_klog = xyes)
+AM_CONDITIONAL(ENABLE_IMKLOG_BSD, test x$os_type = xbsd)
+AM_CONDITIONAL(ENABLE_IMKLOG_LINUX, test x$os_type = xlinux)
#
# SYSLOG_UNIXAF
@@ -455,6 +480,19 @@ AC_ARG_ENABLE(rsyslogd,
AM_CONDITIONAL(ENABLE_RSYSLOGD, test x$enable_rsyslogd = xyes)
+# Mail support (so far we do not need a library, but we need to turn this on and off)
+AC_ARG_ENABLE(mail,
+ [AS_HELP_STRING([--enable-mail],[Enable mail support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mail="yes" ;;
+ no) enable_mail="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mail) ;;
+ esac],
+ [enable_mail=no]
+)
+AM_CONDITIONAL(ENABLE_MAIL, test x$enable_mail = xyes)
+
+
# RELP support
AC_ARG_ENABLE(relp,
[AS_HELP_STRING([--enable-relp],[Enable RELP support @<:@default=no@:>@])],
@@ -466,7 +504,7 @@ AC_ARG_ENABLE(relp,
[enable_relp=no]
)
if test "x$enable_relp" = "xyes"; then
- PKG_CHECK_MODULES(RELP, relp)
+ PKG_CHECK_MODULES(RELP, relp >= 0.1.1)
fi
AM_CONDITIONAL(ENABLE_RELP, test x$enable_relp = xyes)
AC_SUBST(RELP_CFLAGS)
@@ -562,6 +600,7 @@ AC_CONFIG_FILES([Makefile \
plugins/ompgsql/Makefile \
plugins/omrelp/Makefile \
plugins/omlibdbi/Makefile \
+ plugins/ommail/Makefile \
plugins/omsnmp/Makefile])
AC_OUTPUT
@@ -569,13 +608,14 @@ echo "****************************************************"
echo "rsyslog will be compiled with the following settings:"
echo
echo "Multithreading support enabled: $enable_pthreads"
-echo "Klog functionality enabled: $enable_klog"
+echo "Klog functionality enabled: $enable_klog ($os_type)"
echo "Regular expressions support enabled: $enable_regexp"
echo "Zlib compression support enabled: $enable_zlib"
echo "MySql support enabled: $enable_mysql"
echo "libdbi support enabled: $enable_libdbi"
echo "PostgreSQL support enabled: $enable_pgsql"
echo "SNMP support enabled: $enable_snmp"
+echo "Mail support enabled: $enable_mail"
echo "RELP support enabled: $enable_relp"
echo "file input module enabled: $enable_imfile"
echo "input template module will be compiled: $enable_imtemplate"
diff --git a/doc/Makefile.am b/doc/Makefile.am
index c1d41cf..518b90e 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -21,6 +21,7 @@ html_files = \
rsyslog_high_database_rate.html \
rsyslog_php_syslog_ng.html \
rsyslog_recording_pri.html \
+ rsyslog_reliable_forwarding.html \
rsyslog_stunnel.html \
syslog-protocol.html \
version_naming.html \
@@ -31,6 +32,9 @@ html_files = \
imfile.html \
imtcp.html \
imgssapi.html \
+ imrelp.html \
+ imuxsock.html \
+ imklog.html \
professional_support.html \
queues.html \
queueWorkerLogic.dia \
@@ -68,6 +72,12 @@ html_files = \
rsconf1_resetconfigvariables.html \
rsconf1_umask.html \
v3compatibility.html \
+ gssapi.html \
+ licensing.html \
+ ommail.html \
+ omrelp.html \
+ status.html \
+ troubleshoot.html \
src/classes.dia
EXTRA_DIST = $(html_files)
diff --git a/doc/Makefile.in b/doc/Makefile.in
index 468bf85..e6d20e6 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -193,6 +193,7 @@ html_files = \
rsyslog_high_database_rate.html \
rsyslog_php_syslog_ng.html \
rsyslog_recording_pri.html \
+ rsyslog_reliable_forwarding.html \
rsyslog_stunnel.html \
syslog-protocol.html \
version_naming.html \
@@ -203,6 +204,9 @@ html_files = \
imfile.html \
imtcp.html \
imgssapi.html \
+ imrelp.html \
+ imuxsock.html \
+ imklog.html \
professional_support.html \
queues.html \
queueWorkerLogic.dia \
@@ -240,6 +244,12 @@ html_files = \
rsconf1_resetconfigvariables.html \
rsconf1_umask.html \
v3compatibility.html \
+ gssapi.html \
+ licensing.html \
+ ommail.html \
+ omrelp.html \
+ status.html \
+ troubleshoot.html \
src/classes.dia
EXTRA_DIST = $(html_files)
diff --git a/doc/features.html b/doc/features.html
index 9573030..13fc34c 100644
--- a/doc/features.html
+++ b/doc/features.html
@@ -1,7 +1,5 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html><head><title>rsyslog features</title>
-
-</head>
+<html><head><title>rsyslog features</title></head>
<body>
<h1>RSyslog - Features</h1>
<p><b>This page lists both current features as well as
@@ -25,19 +23,19 @@ to MySQL databases</a></li>
<li> native support for writing to Postgres databases</li>
<li>direct support for Firebird/Interbase,
OpenTDS (MS SQL, Sybase), SQLLite, Ingres, Oracle, and mSQL via libdbi,
-a database abstraction layer (almost as good as native)</li>
+a database abstraction layer (almost as good as native)</li><li>native support for <a href="ommail.html">sending mail messages</a> (first seen in 3.17.0)</li>
<li>support for (plain) tcp based syslog - much better
reliability</li>
<li>support for sending and receiving compressed syslog messages</li>
<li>support for on-demand on-disk spooling of messages that can
not be processed fast enough (a great feature for <a href="rsyslog_high_database_rate.html">writing massive
-amounts of syslog messages to a database</a>)</li>
+amounts of syslog messages to a database</a>)</li><li>support for selectively <a href="http://wiki.rsyslog.com/index.php/OffPeakHours">processing messages only during specific timeframes</a> and spooling them to disk otherwise</li>
<li>ability to monitor text files and convert their contents
into syslog messages (one per line)</li>
<li>ability to configure backup syslog/database servers - if
the primary fails, control is switched to a prioritized list of backups</li>
<li>support for receiving messages via reliable <a href="http://www.monitorware.com/Common/en/glossary/rfc3195.php">
-RFC 3195</a> delivery</li>
+RFC 3195</a> delivery (a bit clumpsy to build right now...)</li>
<li>ability to generate file names and directories (log
targets) dynamically, based on many different properties</li>
<li>control of log output format, including ability to present
diff --git a/doc/gssapi.html b/doc/gssapi.html
new file mode 100644
index 0000000..400be4a
--- /dev/null
+++ b/doc/gssapi.html
@@ -0,0 +1,118 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><title>GSSAPI module support in rsyslog v3</title>
+
+</head>
+<body>
+<h1>GSSAPI module support in rsyslog v3</h1>
+<p style="font-weight: bold;">What is it good for.</p>
+<ul style="margin-left: 1.25cm;">
+<li>
+client-serverauthentication </li>
+<li>
+Log
+messages encryption </li>
+</ul>
+<p class="P5"> </p>
+<p class="P3"><span style="font-weight: bold;">Requirements.</span>
+</p>
+<ul>
+<li>Kerberos infrastructure</li>
+<li>rsyslog, rsyslog-gssapi</li>
+</ul>
+<p> </p>
+<p><span style="font-weight: bold;">Configuration.</span>
+</p>
+<p>Let's assume there are 3 machines in kerberos Realm: </p>
+<ul>
+<li>the
+first is running KDC (Kerberos Authentication Service and Key
+Distribution Center),</li>
+<li>the second is a client sending its logs to the server,</li>
+<li>the third is receiver, gathering all logs.</li>
+</ul>
+<p class="P7"> </p>
+<p class="P10"><span style="font-style: italic;">1.
+KDC:</span> </p>
+<ul>
+<li>Kerberos
+database must be properly set-up on KDC machine first. Use
+kadmin/kadmin.local to do that. Two principals need to be add in our
+case:</li>
+</ul>
+<ol style="margin-left: 1.25cm; list-style-type: decimal;">
+<li>
+<p>sender@REALM.ORG
+</p>
+</li>
+</ol>
+<ul>
+<li>client must have ticket for pricipal sender</li>
+<li>REALM.ORG is kerberos Realm</li>
+</ul>
+<ol style="margin-left: 1.25cm; list-style-type: decimal;">
+<li>host/receiver.mydomain.com@REALM.ORG - service principal</li>
+</ol>
+<ul>
+<li>Use ktadd to export service principal and transfer it to
+/etc/krb5.keytab
+on receiver </li>
+</ul>
+<p><span style="font-style: italic;">2. CLIENT:</span>
+</p>
+<ul>
+<li>set-up rsyslog, in /etc/rsyslog.conf</li>
+<li>$ModLoad omgssapi.so - load output gss module </li>
+<li>$GSSForwardServiceName
+otherThanHost - set the name of service principal, "host" is the
+default one</li>
+<li>*.* :omgssapi:receiver.mydomain.com - action line, forward
+logs to receiver</li>
+<li>kinit root - get the TGT ticket</li>
+<li>service rsyslog start
+<p class="P14" style="margin-left: 0.25cm;"> </p>
+</li>
+</ul>
+<p><span style="font-style: italic;">3. SERVER:</span>
+</p>
+<ul>
+<li class="P14" style="margin-left: 0cm;">
+<p class="P14" style="margin-left: 0.25cm;">set-up
+rsyslog, in /etc/rsyslog.conf </p>
+</li>
+<li class="P16">
+<p class="P16" style="margin-left: 0.25cm;">$ModLoad
+<a href="imgssapi.html">imgssapi.so</a> - load input gss module </p>
+</li>
+<li class="P16">
+<p class="P16" style="margin-left: 0.25cm;">$InputGSSServerServiceName
+otherThanHost - set the name of service principal, "host" is the
+default one </p>
+</li>
+<li class="P16">
+<p class="P16" style="margin-left: 0.25cm;">$InputGSSServerPermitPlainTCP
+on - accept GSS and TCP connections (not authenticated senders), off by
+default </p>
+</li>
+<li class="P16">
+<p class="P16" style="margin-left: 0.25cm;">$InputGSSServerRun
+514 - run server on port </p>
+</li>
+<li class="P14" style="margin-left: 0cm;">
+<p class="P14" style="margin-left: 0.25cm;">service
+rsyslog start </p>
+</li>
+</ul>
+<span style="font-weight: bold;">The picture demonstrate
+how things work.</span>
+<p class="P18"> </p>
+<img src="gssapi.png" alt="rsyslog gssapi support">
+<p>[<a href="rsyslog_conf.html">rsyslog.conf overview</a>]
+[<a href="manual.html">manual index</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p>
+<p><font size="2">This documentation is part of the
+<a href="http://www.rsyslog.com/">rsyslog</a>
+project.<br>
+Copyright © 2008 by <a href="http://www.gerhards.net/rainer">Rainer
+Gerhards</a> and
+<a href="http://www.adiscon.com/">Adiscon</a>.
+Released under the GNU GPL version 3 or higher.</font></p>
+</body></html> \ No newline at end of file
diff --git a/doc/imgssapi.html b/doc/imgssapi.html
index af15e59..cf16eb0 100644
--- a/doc/imgssapi.html
+++ b/doc/imgssapi.html
@@ -10,7 +10,9 @@
<p><b>Description</b>:</p>
<p>Provides the ability to receive syslog messages from the
network protected via Kerberos 5 encryption and authentication. This
-module also accept plain tcp syslog messages on the same port if configured to do so. If you need just plain tcp, use&nbsp; <a href="imtcp.html">imtcp</a> instead.</p>
+module also accept plain tcp syslog messages on the same port if configured to do so. If you need just plain tcp, use <a href="imtcp.html">imtcp</a> instead.</p>
+<p>There is also an <a href="gssapi.html">overview of gssapi support in rsyslog</a> available. We recommend reading
+it before digging into the configuration parameters.</p>
<p><b>Configuration Directives</b>:</p>
<ul>
<li>InputGSSServerRun &lt;port&gt;<br>
@@ -47,4 +49,4 @@ Copyright © 2008 by <a href="http://www.gerhards.net/rainer">Rainer
Gerhards</a> and
<a href="http://www.adiscon.com/">Adiscon</a>.
Released under the GNU GPL version 3 or higher.</font></p>
-</body></html> \ No newline at end of file
+</body></html>
diff --git a/doc/imklog.html b/doc/imklog.html
new file mode 100644
index 0000000..b5b21e8
--- /dev/null
+++ b/doc/imklog.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+<meta http-equiv="Content-Language" content="en"><title>Kernel Log Input Module (imklog)</title>
+
+</head>
+<body>
+<h1>Kernel Log Input Module</h1>
+<p><b>Module Name:&nbsp;&nbsp;&nbsp; imklog</b></p>
+<p><b>Author: </b>Rainer Gerhards
+&lt;rgerhards@adiscon.com&gt;</p>
+<p><b>Description</b>:</p>
+<p>Reads messages from the kernel log and submits them to the
+syslog engine.</p>
+<p><b>Configuration Directives</b>:</p>
+<ul>
+<li><strong>$KLogInternalMsgFacility
+&lt;facility&gt;</strong><br>
+The facility which messages internally generated by imklog will have.
+imklog generates some messages of itself (e.g. on problems, startup and
+shutdown) and these do not stem from the kernel. Historically, under
+Linux, these too have "kern" facility. Thus, on Linux platforms the
+default is "kern" while on others it is "syslogd". You usually do not
+need to specify this configuratin directive - it is included primarily
+for few limited cases where it is needed for good reason. Bottom line:
+if you don't have a good idea why you should use this setting, do not
+touch it.</li>
+<li><span style="font-weight: bold;">$KLogPermitNonKernelFacility
+[on/<span style="font-style: italic;">off</span>]<br>
+</span>At least under BSD the kernel log may contain entries
+with non-kernel facilities. This setting controls how those are
+handled. The default is "off", in which case these messages are
+ignored. Switch it to on to submit non-kernel messages to rsyslog
+processing.<span style="font-weight: bold;"></span></li>
+<li><span style="font-weight: bold;"></span>$DebugPrintKernelSymbols
+(imklog) [on/<b>off</b>]<br>
+Linux only, ignored on other platforms (but may be specified)</li>
+<li>$klogSymbolLookup (imklog) [on/<b>off</b>] --
+disables imklog kernel symbol translation (former klogd -x option). NOTE that
+this option is counter-productive on recent kernels (>= 2.6) because the
+kernel already does the symbol translation and this option breaks the information.<br>
+<b>This option is scheduled for removal, probably with version 4.x.</b> Do not use
+it except if you have a very good reason. If you have one, let us know
+because otherwise new versions will no longer support it.<br>
+Linux only, ignored on other platforms (but may be specified)</li>
+<li>$klogUseSyscallInterface (imklog)&nbsp; [on/<b>off</b>]
+-- former klogd -s option<br>
+Linux only, ignored on other platforms (but may be specified)</li>
+<li>$klogSymbolsTwice (imklog) [on/<b>off</b>] --
+former klogd -2 option<br>
+Linux only, ignored on other platforms (but may be specified)<br style="font-weight: bold;">
+</li>
+</ul>
+<b>Caveats/Known Bugs:</b>
+<p>This is obviously platform specific and requires platform
+drivers.
+Currently, imklog functionality is available on Linux and BSD.</p>
+<p><b>Sample:</b></p>
+<p>The following sample pulls messages from the kernel log. All
+parameters are left by default, which is usually a good idea. Please
+note that loading the plugin is sufficient to activate it. No directive
+is needed to start pulling kernel messages.<br>
+</p>
+<textarea rows="15" cols="60">$ModLoad imklog
+</textarea>
+<p>[<a href="rsyslog_conf.html">rsyslog.conf overview</a>]
+[<a href="manual.html">manual index</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p>
+<p><font size="2">This documentation is part of the
+<a href="http://www.rsyslog.com/">rsyslog</a>
+project.<br>
+Copyright © 2008 by <a href="http://www.gerhards.net/rainer">Rainer
+Gerhards</a> and
+<a href="http://www.adiscon.com/">Adiscon</a>.
+Released under the GNU GPL version 3 or higher.</font></p>
+</body></html>
diff --git a/doc/imrelp.html b/doc/imrelp.html
new file mode 100644
index 0000000..bfdaad8
--- /dev/null
+++ b/doc/imrelp.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+<meta http-equiv="Content-Language" content="en"><title>RELP Input Module</title>
+
+</head>
+<body>
+<h1>RELP Input Module</h1>
+<p><b>Module Name:&nbsp;&nbsp;&nbsp; imrelp</b></p>
+<p><b>Author: Rainer Gerhards</b></p>
+<p><b>Description</b>:</p>
+<p>Provides the ability to receive syslog messages via the
+reliable RELP protocol. This module requires <a href="http://www.librelp.com">librelp</a> to be
+present on the system. From the user's point of view, imrelp works much
+like imtcp or imgssapi, except that no message loss can occur. Please
+note that with the currently supported relp protocol version, a minor
+message duplication may occur if a network connection between the relp
+client and relp server breaks after the client could successfully send
+some messages but the server could not acknowledge them. The window of
+opportunity is very slim, but in theory this is possible. Future
+versions of RELP will prevent this. Please also note that rsyslogd may
+lose a few messages if rsyslog is shutdown while a network conneciton
+to the server is broken and could not yet be recovered. Future version
+of RELP support in rsyslog will prevent that. Please note that both
+scenarios also exists with plain tcp syslog. RELP, even with the small
+nits outlined above, is a much more reliable solution than plain tcp
+syslog and so it is highly suggested to use RELP instead of plain tcp.
+Clients send messages to the RELP server via omrelp.</p>
+<p><b>Configuration Directives</b>:</p>
+<ul>
+<li>InputRELPServerRun &lt;port&gt;<br>
+Starts a RELP server on selected port</li>
+</ul>
+<b>Caveats/Known Bugs:</b>
+<ul>
+<li>see description</li>
+</ul>
+<p><b>Sample:</b></p>
+<p>This sets up a RELP server on port 20514.<br>
+</p>
+<textarea rows="15" cols="60">$ModLoad imrelp # needs to be done just once
+$InputRELPServerRun 20514
+</textarea>
+<p>[<a href="rsyslog_conf.html">rsyslog.conf overview</a>]
+[<a href="manual.html">manual index</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p>
+<p><font size="2">This documentation is part of the
+<a href="http://www.rsyslog.com/">rsyslog</a>
+project.<br>
+Copyright © 2008 by <a href="http://www.gerhards.net/rainer">Rainer
+Gerhards</a> and
+<a href="http://www.adiscon.com/">Adiscon</a>.
+Released under the GNU GPL version 3 or higher.</font></p>
+</body></html>
diff --git a/doc/imuxsock.html b/doc/imuxsock.html
new file mode 100644
index 0000000..ee367db
--- /dev/null
+++ b/doc/imuxsock.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+<meta http-equiv="Content-Language" content="en"><title>Unix Socket Input</title>
+
+</head>
+<body>
+<h1>Unix Socket Input</h1>
+<p><b>Module Name:&nbsp;&nbsp;&nbsp; imuxsock</b></p>
+<p><b>Author: </b>Rainer Gerhards
+&lt;rgerhards@adiscon.com&gt;</p>
+<p><b>Description</b>:</p>
+<p>Provides the ability to accept syslog messages via local Unix
+sockets. Most importantly, this is the mechanism by which the syslog(3)
+call delivers syslog messages to rsyslogd. So you need to have this
+module loaded to read the system log socket and be able to process log
+messages from applications running on the local system.</p><p>Application-provided
+timestamps are ignored by default. This is needed, as some programs
+(e.g. sshd)&nbsp;log with inconsistent timezone information, what
+messes up the local logs (which by default don't even contain time zone
+information). This seems to be consistent with what sysklogd did for
+the past four years. Alternate behaviour may be desirable if
+gateway-like processes send messages via the local log slot - in this
+case, it can be enabled via the
+$InputUnixListenSocketIgnoreMsgTimestamp and $SystemLogSocketIgnoreMsgTimestamp config directives</p><p><b>Configuration Directives</b>:</p>
+<ul>
+<li><span style="font-weight: bold;">$InputUnixListenSocketIgnoreMsgTimestamp</span> [<span style="font-weight: bold;">on</span>/off]<strong></strong><br>Ignore timestamps included in the message. Applies to the next socket being added.</li><li><span style="font-weight: bold;">$SystemLogSocketIgnoreMsgTimestamp</span> [<span style="font-weight: bold;">on</span>/off]<br>Ignore timestamps included in the messages, applies to messages received via the system log socket.</li><li><span style="font-weight: bold;">$OmitLocalLogging</span> (imuxsock) [on/<b>off</b>] --
+former -o option</li><li><span style="font-weight: bold;">$SystemLogSocketName</span> &lt;name-of-socket&gt; --
+former -p option</li><li><span style="font-weight: bold;">$AddUnixListenSocket</span> &lt;name-of-socket&gt; adds
+additional unix socket, default none -- former -a option</li></ul>
+<b>Caveats/Known Bugs:</b><br>
+<br>
+This documentation is sparse and incomplete.
+<p><b>Sample:</b></p>
+<p>The following sample is the minimum setup required to accept syslog messages from applications running on the local system.<br>
+</p>
+<textarea rows="15" cols="60">$ModLoad imuxsock # needs to be done just once
+</textarea>
+<p>[<a href="rsyslog_conf.html">rsyslog.conf overview</a>]
+[<a href="manual.html">manual index</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p>
+<p><font size="2">This documentation is part of the
+<a href="http://www.rsyslog.com/">rsyslog</a>
+project.<br>
+Copyright © 2008 by <a href="http://www.gerhards.net/rainer">Rainer
+Gerhards</a> and
+<a href="http://www.adiscon.com/">Adiscon</a>.
+Released under the GNU GPL version 3 or higher.</font></p>
+</body></html> \ No newline at end of file
diff --git a/doc/licensing.html b/doc/licensing.html
new file mode 100644
index 0000000..93a5093
--- /dev/null
+++ b/doc/licensing.html
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+<title>rsyslog licensing</title>
+
+</head>
+<body>
+<h1>rsyslog licensing</h1>
+<p><b>Most important things first: if you intend to use rsyslog inside a GPLv3 compatible project, you are free to do so.</b> You don't even need to continue reading.
+If you intend to use rsyslog inside a non-GPLv3
+compatible project, rsyslog offers you some liberties to do that, too. However, you then need
+to study the licensing details in depth.
+<p>The project hopes this is a good compromise, which also gives a boost to fellow free
+software developers who release under GPLv3.
+<p>And now on to the dirty and boring license details, still on a executive summary level. For the
+real details, check source files and the files COPYING and COPYING.LESSER inside the distribution.
+<p>The rsyslog package contains several components:
+<ul>
+<li>the rsyslog core programs (like rsyslogd)
+<li>plugins (like imklog, omrelp, ...)
+<li>the rsyslog runtime library
+</ul>
+<p>Each of these components can be thought of as individual projects. In fact, some of the
+plugins have different main authors than the rest of the rsyslog package. All of these
+components are currently put together into a single "rsyslog" package (tarball) for
+convinience: this makes it easier to distribute a consistent version where everything
+is included (and in the right versions) to build a full system. Platform package
+maintainers in general take the overall package and split off the individual components, so that
+users can install only what they need. In source installations, this can be done via the
+proper ./configure switches.
+<p>However, while it is convenient to package all parts in a single tarball, it does not
+imply all of them are necessarily covered by the same license. Traditionally, GPL licenses
+are used for rsyslog, because the project would like to provide free software. GPLv3 has been
+used since around 2008 to help fight for our freedom. All rsyslog core programs are
+released under GPLv3. But, from the beginning on, plugins were separate projects and we did not
+impose and license restrictions on them. So even though all plugins that currently ship with
+the rsyslog package are also placed under GPLv3, this can not taken for granted. You need
+to check each plugins license terms if in question - this is especially important for
+plugins that do NOT ship as part of the rsyslog tarball.
+<p>In order to make rsyslog technology available to a broader range of applications,
+the rsyslog runtime is, at least partly, licensed under LGPL. If in doubt, check the source file
+licensing comments. As of now, the following files are licensed under LGPL:
+<ul>
+<li>queue.c/.h
+<li>wti.c/.h
+<li>wtp.c/.h
+<li>vm.c/.h
+<li>vmop.c/.h
+<li>vmprg.c/.h
+<li>vmstk.c/.h
+<li>expr.c/.h
+<li>sysvar.c/.h
+<li>ctok.c/.h
+<li>ctok_token.c/.h
+<li>regexp.c/.h
+<li>sync.c/.h
+<li>stream.c/.h
+<li>var.c/.h
+</ul>
+This list will change as time of the runtime modularization. At some point in the future, there will
+be a well-designed set of files inside a runtime library branch and all of these will be LGPL. Some
+select extras will probably still be covered by GPL. We are following a similar licensing
+model in GnuTLS, which makes effort to reserve some functionality exclusively to open source
+projects.
+<p>[<a href="manual.html">manual index</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p>
+<p><font size="2">This documentation is part of the
+<a href="http://www.rsyslog.com/">rsyslog</a>
+project.<br>
+Copyright &copy; 2008 by <a href="http://www.gerhards.net/rainer">Rainer
+Gerhards</a> and
+<a href="http://www.adiscon.com/">Adiscon</a>. Last Update: 2008-04-15.
+Released under the GNU GPL version 3 or higher.</font></p>
+</body></html>
diff --git a/doc/manual.html b/doc/manual.html
index 21cfe39..eb5fe52 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -16,7 +16,7 @@ relay chains while at the same time being very easy to setup for the
novice user. And as we know what enterprise users really need, there is
also <a href="professional_support.html">professional
rsyslog support</a> available directly from the source!</p>
-<p><b>This documentation is for version 3.16.2 (v3-stable branch) of rsyslog.</b>
+<p><b>This documentation is for version 3.18.1 (v3-stable branch) of rsyslog.</b>
Visit the <i> <a href="http://www.rsyslog.com/doc-status.html">rsyslog status page</a></i></b> to obtain current
version information and project status.
</p><p><b>If you like rsyslog, you might
@@ -31,8 +31,8 @@ if you do not read the doc, but doing so will definitely improve your experience
<p><span style="font-weight: bold;"></span><b>Follow
the links below for the</b><br></p><ul>
-<li><a href="rsyslog_conf.html">configuration file
-syntax (rsyslog.conf)</a></li>
+<li><a href="troubleshoot.html">troubleshooting rsyslog problems</a></li>
+<li><a href="rsyslog_conf.html">configuration file syntax (rsyslog.conf)</a></li>
<li> <a href="property_replacer.html">property
replacer, an important core component</a></li>
<li>a commented <a href="sample.conf.html">sample
@@ -50,22 +50,20 @@ modules</a></li><li><a href="man_rsyslogd.html">rsyslogd man page</a>
<p><b>We have some in-depth papers on</b></p>
<ul>
<li><a href="install.html">installing rsyslog</a></li>
-<li><a href="ipv6.html">rsyslog and IPv6</a>
-(which is fully supported)</li>
-<li><a href="rsyslog_stunnel.html">ssl-encrypting
-syslog with stunnel</a></li>
-<li><a href="rsyslog_mysql.html">writing syslog
-messages to MySQL (and other databases as well)</a></li>
-<li><a href="rsyslog_high_database_rate.html">writing
-massive amounts of syslog messages to a database</a></li>
+<li><a href="ipv6.html">rsyslog and IPv6</a> (which is fully supported)</li>
+<li><a href="rsyslog_stunnel.html">ssl-encrypting syslog with stunnel</a></li>
+<li><a href="rsyslog_mysql.html">writing syslog messages to MySQL (and other databases as well)</a></li>
+<li><a href="rsyslog_high_database_rate.html">writing massive amounts of syslog messages to a database</a></li>
+<li><a href="rsyslog_reliable_forwarding.html">reliable forwarding to a remote server</a></li>
<li><a href="rsyslog_php_syslog_ng.html">using
php-syslog-ng with rsyslog</a></li>
<li><a href="rsyslog_recording_pri.html">recording
the syslog priority (severity and facility) to the log file</a></li>
<li><a href="http://www.rsyslog.com/Article19.phtml">preserving
-syslog sender over NAT</a> (online only)</li><li><a href="gssapi.html">an overview and howto of rsyslog gssapi support</a></li>
+syslog sender over NAT</a> (online only)</li>
+<li><a href="gssapi.html">an overview and howto of rsyslog gssapi support</a></li>
<li><a href="debug.html">debug support in rsyslog</a></li>
-<li><a href="dev_queue.html">the rsyslog message queue object</a></li>
+<li><a href="dev_queue.html">the rsyslog message queue object (developer's view)</a></li>
</ul>
<p>Our <a href="history.html">rsyslog history</a>
page is for you if you would like to learn a little more
diff --git a/doc/ommail.html b/doc/ommail.html
new file mode 100644
index 0000000..62ded6d
--- /dev/null
+++ b/doc/ommail.html
@@ -0,0 +1,128 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><title>mail output module - sending syslog messages via mail</title>
+
+</head>
+<body>
+<h1>Mail Output Module (ommail)</h1>
+<p><b>Module Name:&nbsp;&nbsp;&nbsp; ommail</b></p>
+<p><b>Available since:&nbsp;&nbsp;&nbsp;</b> 3.17.0</p>
+<p><b>Author: </b>Rainer Gerhards
+&lt;rgerhards@adiscon.com&gt;</p>
+<p><b>Description</b>:</p>
+<p>This module supports sending syslog messages via mail. Each
+syslog message is sent via its own mail. Obviously, you will want to
+apply rigorous filtering, otherwise your mailbox (and mail server) will
+be heavily spammed. The ommail plugin is primarily meant for alerting
+users. As such, it is assume that mails will only be sent in an
+extremely limited number of cases.</p>
+<p>Please note that ommail is especially well-suited to work in
+tandem with <a href="imfile.html">imfile</a> to
+watch files for the occurence of specific things to be alerted on. So
+its scope is far broader than forwarding syslog messages to mail
+recipients.</p>
+Ommail uses two templates, one for the mail body and one for the
+subject line. If neither is provided, a quite meaningless subject line
+is used and the mail body will be a syslog message just as if it were
+written to a file. It is expected that the users customizes both
+messages. In an effort to support cell phones (including SMS gateways),
+there is an option to turn off the body part at all. This is considered
+to be useful to send a short alert to a pager-like device.<br>
+<br>
+It is highly recommended to use the&nbsp; "<span style="font-weight: bold;">$ActionExecOnlyOnceEveryInterval
+&lt;seconds&gt;</span>" directive to limit the amount of
+mails that potentially be generated. With it, mails are sent at most in
+a &lt;seconds&gt; interval. This may be your life safer. And
+remember that an hour has 3,600 seconds, so if you would like to
+receive mails at most once every two hours, include a
+"$ActionExecOnlyOnceEveryInterval 7200" immediately before the ommail
+action. Messages sent more frequently are simpy discarded.<span style="font-weight: bold;"></span>
+<p><b>Configuration Directives</b>:</p>
+<ul>
+<li><span style="font-weight: bold;">$ActionMailSMTPServer</span><br>
+Name or IP address of the SMTP server to be used. Must currently be
+set. The default is 127.0.0.1, the SMTP server on the local machine.
+Obviously it is not good to expect one to be present on each machine,
+so this value should be specified.<br>
+</li>
+<li><span style="font-weight: bold;">$ActionMailSMTPPort</span><br>
+Port number or name of the SMTP port to be used. The default is 25, the
+standard SMTP port.</li>
+<li><span style="font-weight: bold;">$ActionMailFrom</span><br>
+The email address used as the senders address. There is no default.</li>
+<li><span style="font-weight: bold;">$ActionMailTo</span><br>
+The recipients email address. There is no default.</li>
+<li><span style="font-weight: bold;">$ActionMailSubject</span><br>
+The name of the <span style="font-weight: bold;">template</span>
+to be used as the mail subject. If this is not specified, a more or
+less meaningless mail subject is generated (we don't tell you the exact
+text because that can change - if you want to have something specific,
+configure it!).</li>
+<li><span style="font-weight: bold;">$ActionMailEnableBody</span><br>
+Setting this to "off" permits to exclude the actual message body. This
+may be useful for pager-like devices or cell phone SMS messages. The
+default is "on", which is appropriate for allmost all cases. Turn it
+off only if you know exactly what you do!</li>
+</ul>
+<b>Caveats/Known Bugs:</b>
+<p>The current ommail implementation supports <span style="font-weight: bold;">SMTP-direct mode</span>
+only. In that mode, the plugin talks to the mail server via SMTP
+protocol. No other process is involved. This mode offers best
+reliability as it is not depending on any external entity except the
+mail server. Mail server downtime is acceptable if the action is put
+onto its own action queue, so that it may wait for the SMTP server to
+come back online. However, the module implements only the bare SMTP
+essentials. Most importantly, it does not provide any authentication
+capabilities. So your mail server must be configured to accept incoming
+mail from ommail without any authentication needs (this may be change
+in the future as need arises, but you may also be referred to
+sendmail-mode).</p>
+<p>In theory, ommail should also offer a mode where it uses the
+sendmail utility to send its mail (<span style="font-weight: bold;">sendmail-mode</span>).
+This is somewhat less reliable (because we depend on an entity we do
+not have close control over - sendmail). It also requires dramatically
+more system ressources, as we need to load the external process (but
+that should be no problem given the expected infrequent number of calls
+into this plugin). The big advantage of sendmail mode is that it
+supports all the bells and whistles of a full-blown SMTP implementation
+and may even work for local delivery without a SMTP server being
+present. Sendmail mode will be implemented as need arises. So if you
+need it, please drop us a line (I nobody does, sendmail mode will
+probably never be implemented).</p>
+<p><b>Sample:</b></p>
+<p>The following sample alerts the operator if the string "hard
+disk fatal failure" is present inside a syslog message. The mail server
+at mail.example.net is used and the subject shall be "disk problem on
+&lt;hostname&gt;". Note how \r\n is included inside the body
+text
+to create line breaks. A message is sent at most once every 6 hours,
+any other messages are silently discarded (or, to be precise, not being
+forwarded - they are still being processed by the rest of the
+configuration file).<br>
+</p>
+<textarea rows="15" cols="80">$ModLoad ommail
+$ActionMailSMTPServer mail.example.net
+$ActionMailFrom rsyslog@example.net
+$ActionMailTo operator@example.net
+$template mailSubject,"disk problem on %hostname%"
+$template mailBody,"RSYSLOG Alert\r\nmsg='%msg%'"
+$ActionMailSubject mailSubject
+# make sure we receive a mail only once in six
+# hours (21,600 seconds ;))
+$ActionExecOnlyOnceEveryInterval 21600
+# the if ... then ... mailBody mus be on one line!
+if $msg contains 'hard disk fatal failure' then :ommail:;mailBody
+</textarea>
+<p>A more advanced example plus a discussion on using the email feature
+inside a reliable system can be found in Rainer's blogpost
+"<a style="font-style: italic;" href="http://rgerhards.blogspot.com/2008/04/why-is-native-email-capability.html">Why
+is native email capability an advantage for a syslogd?</a>"
+<p>[<a href="rsyslog_conf.html">rsyslog.conf overview</a>]
+[<a href="manual.html">manual index</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p>
+<p><font size="2">This documentation is part of the
+<a href="http://www.rsyslog.com/">rsyslog</a>
+project.<br>
+Copyright &copy; 2008 by <a href="http://www.gerhards.net/rainer">Rainer
+Gerhards</a> and
+<a href="http://www.adiscon.com/">Adiscon</a>.
+Released under the GNU GPL version 3 or higher.</font></p>
+</body></html>
diff --git a/doc/omrelp.html b/doc/omrelp.html
new file mode 100644
index 0000000..0952cc7
--- /dev/null
+++ b/doc/omrelp.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+<meta http-equiv="Content-Language" content="en"><title>RELP Output Module (omrelp)</title>
+
+</head>
+<body>
+<h1>RELP Output Module (omlibdbi)</h1>
+<p><b>Module Name:&nbsp;&nbsp;&nbsp; omrelp</b></p>
+<p><b>Author: </b>Rainer Gerhards
+&lt;rgerhards@adiscon.com&gt;</p>
+<p><b>Description</b>:</p>
+<p>This module supports sending syslog messages over the reliable
+RELP protocol. For RELP's advantages over plain tcp syslog, please see
+the documentation for <a href="imrelp.html">imrelp</a>
+(the server counterpart).&nbsp;</p>
+<span style="font-weight: bold;">Setup</span>
+<p>Please note the <a href="http://www.librelp.com">librelp</a>
+is required for imrelp (it provides the core relp protocol
+implementation).</p>
+<p><b>Configuration Directives</b>:</p>
+<p>This module uses old-style action configuration to keep
+consistent with the forwarding rule. So far, no additional
+configuration directives can be specified. To send a message via RELP,
+use</p>
+<p>*.*
+&nbsp;:omrelp:&lt;sever&gt;:&lt;port&gt;;&lt;template&gt;</p>
+<p>just as you use&nbsp;</p>
+<p>*.*
+&nbsp;@@&lt;sever&gt;:&lt;port&gt;;&lt;template&gt;</p>
+<p>to forward a message via plain tcp syslog.</p>
+<b>Caveats/Known Bugs:</b>
+<p>See <a href="imrelp.html">imrelp</a>,
+which documents them.&nbsp;</p>
+<p><b>Sample:</b></p>
+<p>The following sample sends all messages to the central server
+"centralserv" at port 2514 (note that that server must run imrelp on
+port 2514). Rsyslog's high-precision timestamp format is used, thus the
+special "RSYSLOG_ForwardFormat" (case sensitive!) template is used.<br>
+</p>
+<textarea rows="15" cols="60">$ModLoad omrelp
+# forward messages to the remote server "myserv" on
+# port 2514
+*.* :omrelp:centralserv:2514;RSYSLOG_ForwardFormat
+</textarea>
+<p>[<a href="rsyslog_conf.html">rsyslog.conf overview</a>]
+[<a href="manual.html">manual index</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p>
+<p><font size="2">This documentation is part of the
+<a href="http://www.rsyslog.com/">rsyslog</a>
+project.<br>
+Copyright © 2008 by <a href="http://www.gerhards.net/rainer">Rainer
+Gerhards</a> and
+<a href="http://www.adiscon.com/">Adiscon</a>.
+Released under the GNU GPL version 3 or higher.</font></p>
+</body></html> \ No newline at end of file
diff --git a/doc/property_replacer.html b/doc/property_replacer.html
index 3484acf..f5fc194 100644
--- a/doc/property_replacer.html
+++ b/doc/property_replacer.html
@@ -1,7 +1,5 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html><head><title>The Rsyslogd Property Replacer</title>
-
-</head>
+<html><head><title>The Rsyslogd Property Replacer</title></head>
<body>
<h1>The Property Replacer</h1>
<p><b>The property replacer is a core component in
@@ -17,7 +15,7 @@ modified by the property replacer. The full syntax is as follows:</p>
<blockquote><b><code>%propname:fromChar:toChar:options%</code></b></blockquote>
<h2>Available Properties</h2>
<p><b><code>propname</code></b> is the
-name of the property to access. It is case-sensitive.
+name of the property to access. It is case-insensitive (prior to 3.17.0, they were case-senstive).
Currently supported are:</p>
<table>
<tbody>
@@ -31,11 +29,11 @@ Currently supported are:</p>
socket. Should be useful for debugging.</td>
</tr>
<tr>
-<td><b>UxTradMsg</b></td>
+<td><b>uxtradmsg</b></td>
<td>will disappear soon - do NOT use!</td>
</tr>
<tr>
-<td><b>HOSTNAME</b></td>
+<td><b>hostname</b></td>
<td>hostname from the message</td>
</tr>
<tr>
@@ -43,7 +41,7 @@ socket. Should be useful for debugging.</td>
<td>alias for HOSTNAME</td>
</tr>
<tr>
-<td><b>FROMHOST</b></td>
+<td><b>fromhost</b></td>
<td>hostname of the system the message was received from
(in a relay chain, this is the system immediately in front of us and
not necessarily the original sender)</td>
@@ -59,16 +57,16 @@ BSD syslogd. For example, when TAG is "named[12345]", programname is
"named".</td>
</tr>
<tr>
-<td><b>PRI</b></td>
+<td><b>pri</b></td>
<td>PRI part of the message - undecoded (single value)</td>
</tr>
<tr>
-<td><b>PRI-text</b></td>
+<td><b>pri-text</b></td>
<td>the PRI part of the message in a textual form (e.g.
"syslog.info")</td>
</tr>
<tr>
-<td><b>IUT</b></td>
+<td><span style="font-weight: bold;">iut</span></td>
<td>the monitorware InfoUnitType - used when talking
to a <a href="http://www.monitorware.com">MonitorWare</a>
backend (also for <a href="http://www.phplogcon.org/">phpLogCon</a>)</td>
@@ -110,67 +108,67 @@ what was provided in the message (in most cases,
only seconds)</td>
</tr>
<tr>
-<td><b>TIMESTAMP</b></td>
+<td><b>timestamp</b></td>
<td>alias for timereported</td>
</tr>
<tr>
-<td><b>PROTOCOL-VERSION</b></td>
+<td><b>protocol-version</b></td>
<td>The contents of the PROTCOL-VERSION field from IETF
draft draft-ietf-syslog-protcol</td>
</tr>
<tr>
-<td><b>STRUCTURED-DATA</b></td>
+<td><b>structured-data</b></td>
<td>The contents of the STRUCTURED-DATA field from IETF
draft draft-ietf-syslog-protocol</td>
</tr>
<tr>
-<td><b>APP-NAME</b></td>
+<td><b>app-name</b></td>
<td>The contents of the APP-NAME field from IETF draft
draft-ietf-syslog-protocol</td>
</tr>
<tr>
-<td><b>PROCID</b></td>
+<td><b>procid</b></td>
<td>The contents of the PROCID field from IETF draft
draft-ietf-syslog-protocol</td>
</tr>
<tr>
-<td height="24"><b>MSGID</b></td>
+<td height="24"><b>msgid</b></td>
<td height="24">The contents of the MSGID field from
IETF draft draft-ietf-syslog-protocol</td>
</tr>
<tr>
-<td><b>$NOW</b></td>
+<td><b>$now</b></td>
<td>The current date stamp in the format YYYY-MM-DD</td>
</tr>
<tr>
-<td><b>$YEAR</b></td>
+<td><b>$year</b></td>
<td>The current year (4-digit)</td>
</tr>
<tr>
-<td><b>$MONTH</b></td>
+<td><b>$month</b></td>
<td>The current month (2-digit)</td>
</tr>
<tr>
-<td><b>$DAY</b></td>
+<td><b>$day</b></td>
<td>The current day of the month (2-digit)</td>
</tr>
<tr>
-<td><b>$HOUR</b></td>
+<td><b>$hour</b></td>
<td>The current hour in military (24 hour) time (2-digit)</td>
</tr>
<tr>
-<td><b>$HHOUR</b></td>
+<td><b>$hhour</b></td>
<td>The current half hour we are in. From minute 0 to 29,
this is always 0 while
from 30 to 59 it is always 1.</td>
</tr>
<tr>
-<td><b>$QHOUR</b></td>
+<td><b>$qhour</b></td>
<td>The current quarter hour we are in. Much like $HHOUR, but values
range from 0 to 3 (for the four quater hours that are in each hour)</td>
</tr>
<tr>
-<td><b>$MINUTE</b></td>
+<td><b>$minute</b></td>
<td>The current minute (2-digit)</td>
</tr>
</tbody>
@@ -255,7 +253,7 @@ Especially useful for PIX.</td>
<td>format as RFC 3339 date</td>
</tr>
<tr>
-<td><b>escape-cc</b></td>
+<td valign="top"><b>escape-cc</b></td>
<td>replace control characters (ASCII value 127 and values
less then 32) with an escape sequence. The sequnce is
"#&lt;charval&gt;" where charval is the 3-digit decimal value
@@ -265,19 +263,53 @@ Note: using this option requires that <a href="rsconf1_escapecontrolcharacterson
is set to off.</td>
</tr>
<tr>
-<td><b>space-cc</b></td>
+<td valign="top"><b>space-cc</b></td>
<td>replace control characters by spaces<br>
Note: using this option requires that <a href="rsconf1_escapecontrolcharactersonreceive.html">$EscapeControlCharactersOnReceive</a>
is set to off.</td>
</tr>
<tr>
-<td><b>drop-cc</b></td>
+<td valign="top"><b>drop-cc</b></td>
<td>drop control characters - the resulting string will
neither contain control characters, escape sequences nor any other
replacement character like space.<br>
Note: using this option requires that <a href="rsconf1_escapecontrolcharactersonreceive.html">$EscapeControlCharactersOnReceive</a>
is set to off.</td>
</tr>
+<tr>
+<td valign="top"><b>sp-if-no-1st-sp</b></td>
+<td>This option looks scary and should probably not be used by a user. For any field
+given, it returns either a single space character or no character at all. Field content
+is never returned. A space is returned if (and only if) the first character of the
+field's content is NOT a space. This option is kind of a hack to solve a problem rooted
+in RFC 3164: 3164 specifies no delimiter between the syslog tag sequence and the actual
+message text. Almost all implementation in fact delemit the two by a space. As of
+RFC 3164, this space is part of the message text itself. This leads to a problem when
+building the message (e.g. when writing to disk or forwarding). Should a delimiting
+space be included if the message does not start with one? If not, the tag is immediately
+followed by another non-space character, which can lead some log parsers to misinterpret
+what is the tag and what the message. The problem finally surfaced when the klog module
+was restructured and the tag correctly written. It exists with other message sources,
+too. The solution was the introduction of this special property replacer option. Now,
+the default template can contain a conditional space, which exists only if the
+message does not start with one. While this does not solve all issues, it should
+work good enough in the far majority of all cases. If you read this text and have
+no idea of what it is talking about - relax: this is a good indication you will never
+need this option. Simply forget about it ;)
+</td>
+</tr>
+<tr>
+<td valign="top"><b>secpath-drop</b></td>
+<td>Drops slashes inside the field (e.g. "a/b" becomes "ab").
+Useful for secure pathname generation (with dynafiles).
+</td>
+</tr>
+<tr>
+<td valign="top"><b>secpath-replace</b></td>
+<td>Replace slashes inside the field by an underscore. (e.g. "a/b" becomes "a_b").
+Useful for secure pathname generation (with dynafiles).
+</td>
+</tr>
</tbody>
</table>
<h2>Further Links</h2>
@@ -288,4 +320,4 @@ to record severity and facility of a message)</li>
<li><a href="rsyslog_conf.html">Configuration file
syntax</a>, this is where you actually use the property replacer.</li>
</ul>
-</body></html> \ No newline at end of file
+</body></html>
diff --git a/doc/queues.html b/doc/queues.html
index 80641d8..a2074d3 100644
--- a/doc/queues.html
+++ b/doc/queues.html
@@ -288,7 +288,17 @@ directive allows to specify how long (in microseconds) dequeueing should be
delayed. While simple, it still is powerful. For example, using a
DequeueSlowdown delay of 1,000 microseconds on a UDP send action ensures that no
more than 1,000 messages can be sent within a second (actually less, as there is
-also some time needed for the processing itself). </p>
+also some time needed for the processing itself).</p><h2>Processing Timeframes</h2><p>Queues
+can be set to dequeue (process) messages only during certain
+timeframes. This is useful if you, for example, would like to transfer
+the bulk of messages only during off-peak hours, e.g. when you have
+only limited bandwidth on the network path the the central server.</p><p>Currently,
+only a single timeframe is supported and, even worse, it can only be
+specified by the hour. It is not hard to extend rsyslog's capabilities
+in this regard - it was just not requested so far. So if you need more
+fine-grained control, let us know and we'll probably implement it.
+There are two configuration directives, both should be used together or
+results are unpredictable:" <i>$&lt;object&gt;QueueDequeueTimeBegin &lt;hour&gt;</i>" and&nbsp;"<i>$&lt;object&gt;QueueDequeueTimeEnd &lt;hour&gt;</i>". The hour parameter must be specified in 24-hour format (so 10pm is 22). A use case for this parameter can be found in the <a href="http://wiki.rsyslog.com/index.php/OffPeakHours">rsyslog wiki</a>. </p>
<h2>Terminating Queues</h2>
<p>Terminating a process sounds easy, but can be complex.
<span style="font-size: 12pt; line-height: 115%; font-family: 'Times New Roman',serif;" lang="EN-US">
diff --git a/doc/rscript_abnf.html b/doc/rscript_abnf.html
index 97de728..278fb59 100644
--- a/doc/rscript_abnf.html
+++ b/doc/rscript_abnf.html
@@ -34,8 +34,8 @@ table... values('&amp;$facility&amp;','&amp;$severity&amp;...?]<br>&nbsp; &nbsp;
<p><font size="2">This documentation is part of the
<a href="http://www.rsyslog.com/">rsyslog</a>
project.<br>
-Copyright © 2008 by <a href="http://www.gerhards.net/rainer">Rainer
+Copyright &copy; 2008 by <a href="http://www.gerhards.net/rainer">Rainer
Gerhards</a> and
<a href="http://www.adiscon.com/">Adiscon</a>.
Released under the GNU GPL version 3 or higher.</font></p>
-</body></html> \ No newline at end of file
+</body></html>
diff --git a/doc/rsyslog_conf.html b/doc/rsyslog_conf.html
index 2a0f0c6..9325f73 100644
--- a/doc/rsyslog_conf.html
+++ b/doc/rsyslog_conf.html
@@ -26,22 +26,30 @@ 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>
+trap output module</li>
+<li><a href="omrelp.html">omrelp</a> - RELP
+output module</li>
<li>omgss - output module for GSS-enabled syslog</li>
<li>ommysql - output module for MySQL</li>
<li>ompgsql - output module for PostgreSQL</li>
<li><a href="omlibdbi.html">omlibdbi</a> -
generic database output module (Firebird/Interbase, MS SQL, Sybase,
SQLLite, Ingres, Oracle, mSQL)</li>
+<li><a href="ommail.html">ommail</a> -
+permits rsyslog to alert folks by mail if something important happens</li>
<li><a href="imfile.html">imfile</a>
--&nbsp; input module for text files</li><li><a href="imrelp.html">imrelp</a> - RELP input module</li>
+-&nbsp; input module for text files</li>
+<li><a href="imrelp.html">imrelp</a> - RELP
+input module</li>
<li>imudp - udp syslog message input</li>
<li><a href="imtcp.html">imtcp</a> - input
plugin for plain tcp syslog</li>
<li><a href="imgssapi.html">imgssapi</a> -
input plugin for plain tcp and GSS-enable syslog</li>
<li>immark - support for mark messages</li>
-<li>imklog - kernel logging</li><li><a href="imuxsock.html">imuxsock</a> - unix sockets, including the system log socket</li>
+<li><a href="imklog.html">imklog</a> - kernel logging</li>
+<li><a href="imuxsock.html">imuxsock</a> -
+unix sockets, including the system log socket</li>
</ul>
<p>Please note that each module provides configuration
directives, which are NOT necessarily being listed below. Also
@@ -64,7 +72,19 @@ unstable...). So you have been warned ;)</p>
many parameter settings modify queue parameters. If in doubt, use the
default, it is usually well-chosen and applicable in most cases.</p>
<ul>
-<li><a href="rsconf1_actionexeconlywhenpreviousissuspended.html">$ActionExecOnlyWhenPreviousIsSuspended</a></li><li>$ActionFileDefaultTemplate [templateName] - sets a new default template for file actions</li><li>$ActionFileEnableSync [on/<span style="font-weight: bold;">off</span>] - enables file syncing capability of omfile</li><li>$ActionForwardDefaultTemplate [templateName] - sets a new default template for UDP and plain TCP forwarding action</li><li>$ActionGSSForwardDefaultTemplate [templateName] - sets a new default template for GSS-API forwarding action</li>
+<li><a href="rsconf1_actionexeconlywhenpreviousissuspended.html">$ActionExecOnlyWhenPreviousIsSuspended</a></li>
+<li>$ActionExecOnlyOnceEveryInterval &lt;seconds&gt; -
+execute action only if the last execute is at last
+&lt;seconds&gt; seconds in the past (more info in <a href="ommail.html">ommail</a>,
+but may be used with any action)</li>
+<li>$ActionFileDefaultTemplate [templateName] - sets a new
+default template for file actions</li>
+<li>$ActionFileEnableSync [on/<span style="font-weight: bold;">off</span>] - enables file
+syncing capability of omfile</li>
+<li>$ActionForwardDefaultTemplate [templateName] - sets a new
+default template for UDP and plain TCP forwarding action</li>
+<li>$ActionGSSForwardDefaultTemplate [templateName] - sets a
+new default template for GSS-API forwarding action</li>
<li>$ActionQueueCheckpointInterval &lt;number&gt;</li>
<li>$ActionQueueDequeueSlowdown &lt;number&gt; [number
is timeout in <i> micro</i>seconds (1000000us is 1sec!),
@@ -98,12 +118,13 @@ default 60000 (1 minute)]</li>
worker threads, default 1, recommended 1</li>
<li>$ActionQueueWorkerThreadMinumumMessages
&lt;number&gt;, default 100</li>
-<li><a href="rsconf1_actionresumeinterval.html">$ActionResumeInterval</a></li><li>$ActionResumeRetryCount &lt;number&gt; [default 0,
+<li><a href="rsconf1_actionresumeinterval.html">$ActionResumeInterval</a></li>
+<li>$ActionResumeRetryCount &lt;number&gt; [default 0,
-1 means eternal]</li>
<li><a href="rsconf1_allowedsender.html">$AllowedSender</a></li>
<li><a href="rsconf1_controlcharacterescapeprefix.html">$ControlCharacterEscapePrefix</a></li>
<li><a href="rsconf1_debugprintcfsyslinehandlerlist.html">$DebugPrintCFSyslineHandlerList</a></li>
-<li>$DebugPrintKernelSymbols (imklog) [on/<b>off</b>]</li>
+
<li><a href="rsconf1_debugprintmodulelist.html">$DebugPrintModuleList</a></li>
<li><a href="rsconf1_debugprinttemplatelist.html">$DebugPrintTemplateList</a></li>
<li><a href="rsconf1_dircreatemode.html">$DirCreateMode</a></li>
@@ -120,14 +141,7 @@ worker threads, default 1, recommended 1</li>
<li><a href="rsconf1_gssforwardservicename.html">$GssForwardServiceName</a></li>
<li><a href="rsconf1_gsslistenservicename.html">$GssListenServiceName</a></li>
<li><a href="rsconf1_gssmode.html">$GssMode</a></li>
-<li><a href="rsconf1_includeconfig.html">$IncludeConfig</a></li>
-<li>$klogSymbolLookup (imklog) [<b>on</b>/off] --
-former klogd -x option</li>
-<li>$klogUseSyscallInterface (imklog)&nbsp; [on/<b>off</b>]
--- former klogd -2 option</li>
-<li>$klogSymbolsTwice (imklog) [on/<b>off</b>] --
-former klogd -s option</li>
-<li>$MainMsgQueueCheckpointInterval &lt;number&gt;</li>
+<li><a href="rsconf1_includeconfig.html">$IncludeConfig</a></li><li>MainMsgQueueCheckpointInterval &lt;number&gt;</li>
<li>$MainMsgQueueDequeueSlowdown &lt;number&gt; [number
is timeout in <i> micro</i>seconds (1000000us is 1sec!),
default 0 (no delay). Simple rate-limiting!]</li>
@@ -166,11 +180,11 @@ worker threads, default 1, recommended 1</li>
(immark)</li>
<li><a href="rsconf1_moddir.html">$ModDir</a></li>
<li><a href="rsconf1_modload.html">$ModLoad</a></li>
-
<li><a href="rsconf1_repeatedmsgreduction.html">$RepeatedMsgReduction</a></li>
<li><a href="rsconf1_resetconfigvariables.html">$ResetConfigVariables</a></li>
<li>$WorkDirectory &lt;name&gt; (directory for spool
-and other work files)</li><li>$UDPServerAddress &lt;IP&gt; (imudp) -- local IP
+and other work files)</li>
+<li>$UDPServerAddress &lt;IP&gt; (imudp) -- local IP
address (or name) the UDP listens should bind to</li>
<li>$UDPServerRun &lt;port&gt; (imudp) -- former
-r&lt;port&gt; option, default 514, start UDP server on this
@@ -302,18 +316,29 @@ template:</p>
DynFile,"/var/log/system-%HOSTNAME%.log"</code></blockquote>
<p>This template can then be used when defining an output
selector line. It will result in something like
-"/var/log/system-localhost.log"</p><p>Template
+"/var/log/system-localhost.log"</p>
+<p>Template
names beginning with "RSYSLOG_" are reserved for rsyslog use. Do NOT
use them if, otherwise you may receive a conflict in the future (and
quite unpredictable behaviour). There is a small set of pre-defined
-templates that you can use without the need to define it:</p><ul><li><span style="font-weight: bold;">RSYSLOG_TraditionalFileFormat</span> - the "old style" default log file format with low-precision timestamps</li><li><span style="font-weight: bold;">RSYSLOG_FileFormat</span> - a modern-style logfile format similar to TraditionalFileFormat, buth with high-precision timestamps and timezone information</li><li><span style="font-weight: bold;">RSYSLOG_TraditionalForwardFormat</span>
+templates that you can use without the need to define it:</p>
+<ul>
+<li><span style="font-weight: bold;">RSYSLOG_TraditionalFileFormat</span>
+- the "old style" default log file format with low-precision timestamps</li>
+<li><span style="font-weight: bold;">RSYSLOG_FileFormat</span>
+- a modern-style logfile format similar to TraditionalFileFormat, buth
+with high-precision timestamps and timezone information</li>
+<li><span style="font-weight: bold;">RSYSLOG_TraditionalForwardFormat</span>
- the traditional forwarding format with low-precision timestamps. Most
-useful if you send&nbsp;messages to other syslogd's or rsyslogd below
-version 3.12.5.</li><li><span style="font-weight: bold;">RSYSLOG_ForwardFormat</span>
+useful if you send&nbsp;messages to other syslogd's or rsyslogd
+below
+version 3.12.5.</li>
+<li><span style="font-weight: bold;">RSYSLOG_ForwardFormat</span>
- a new high-precision forwarding format very similar to the
traditional one, but with high-precision timestamps and timezone
information. Recommended to be used when sending messages to rsyslog
-3.12.5 or above.</li><li><span style="font-weight: bold;">RSYSLOG_SyslogProtocol23Format</span>
+3.12.5 or above.</li>
+<li><span style="font-weight: bold;">RSYSLOG_SyslogProtocol23Format</span>
- the format specified in IETF's internet-draft
ietf-syslog-protocol-23, which is assumed to be come the new syslog
standard RFC. This format includes several improvements. The rsyslog
@@ -321,7 +346,8 @@ message parser understands this format, so you can use it together with
all relatively recent versions of rsyslog. Other syslogd's may get
hopelessly confused if receiving that format, so check before you use
it. Note that the format is unlikely to change when the final RFC comes
-out, but this may happen.</li></ul>
+out, but this may happen.</li>
+</ul>
<h2>Output Channels</h2>
<p>Output Channels are a new concept first introduced in rsyslog
0.9.0. <b>As of this writing, it is most likely that they will
@@ -524,7 +550,8 @@ once they are implemented, it can make very much sense
</tr>
<tr>
<td>regex</td>
-<td>Compares the property against the provided POSIX regular
+<td>Compares the property against the provided POSIX
+regular
expression.</td>
</tr>
</tbody>
@@ -567,10 +594,12 @@ code), this can be done easily by:</p>
"ID-4711". Please note that the comparison is case-sensitive, so it
would not match if "id-4711" would be contained in the message.</p>
<p><code><b>:msg, regex, "fatal .* error"</b></code></p>
-<p>This filter uses a POSIX regular expression. It matches when the
+<p>This filter uses a POSIX regular expression. It matches when
+the
string contains the words "fatal" and "error" with anything in between
(e.g. "fatal net error" and "fatal lib error" but not "fatal error" as
-two spaces are required by the regular expression!).</p><p>Getting property-based filters right can sometimes be
+two spaces are required by the regular expression!).</p>
+<p>Getting property-based filters right can sometimes be
challenging. In order to help you do it with as minimal effort as
possible, rsyslogd spits out debug information for all property-based
filters during their evaluation. To enable this, run rsyslogd in
@@ -635,9 +664,12 @@ startswith 'DEVNAME' and <span style="font-weight: bold;">not</span>
($msg contains 'error1' or $msg contains
'error0') then /var/log/somelog<br>
</code>
-<br>If you would like to do case-insensitive comparisons, use
+<br>
+If you would like to do case-insensitive comparisons, use
"contains_i" instead of "contains" and "startswith_i" instead of
-"startswith".<br><br>Note that regular expressions are currently NOT
+"startswith".<br>
+<br>
+Note that regular expressions are currently NOT
supported in expression-based filters. These will be added later when
function support is added to the expression engine (the reason is that
regular expressions will be a separate loadable module, which requires
diff --git a/doc/rsyslog_ng_comparison.html b/doc/rsyslog_ng_comparison.html
index 2a1d15b..2841333 100644
--- a/doc/rsyslog_ng_comparison.html
+++ b/doc/rsyslog_ng_comparison.html
@@ -1,12 +1,11 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html><head>
-<meta content="de" http-equiv="Content-Language"><title>rsyslog vs. syslog-ng - a comparison</title>
+<html><head><title>rsyslog vs. syslog-ng - a comparison</title>
</head>
<body>
<h1>rsyslog vs. syslog-ng</h1>
<p><small><i>Written by <a href="http://www.gerhards.net/rainer">Rainer Gerhards</a>
-(2008-02-28)</i></small></p>
+(2008-04-08)</i></small></p>
<p>We have often been asked about a comparison sheet between
rsyslog and syslog-ng. Unfortunately, I do not know much about
syslog-ng, I did not even use it once. Also, there seems to be no
@@ -122,7 +121,9 @@ based framing on syslog/tcp connections</td>
<td valign="top">yes</td>
</tr>
<tr>
-<td valign="top">syslog over RELP<br>this is a truely reliable solution (plain tcp syslog can lose messages!)</td>
+<td valign="top">syslog over RELP<br>
+truly reliable message delivery (<a href="http://rgerhards.blogspot.com/2008/04/on-unreliability-of-plain-tcp-syslog.html">Why
+is plain tcp syslog not reliable?</a>)</td>
<td valign="top">yes</td>
<td valign="top">no</td>
</tr>
@@ -337,6 +338,15 @@ be placed on different disk</td>
<td valign="top">no</td>
</tr>
<tr>
+<td valign="top">ability to process spooled
+messages only during a configured timeframe (e.g. process messages only
+during off-peak hours, during peak hours they are enqueued only)</td>
+<td valign="top"><a href="http://wiki.rsyslog.com/index.php/OffPeakHours">yes</a><br>
+(can independently be configured for the main queue and each action
+queue)</td>
+<td valign="top">no</td>
+</tr>
+<tr>
<td valign="top">ability to configure backup
syslog/database servers </td>
<td valign="top">yes</td>
@@ -416,6 +426,10 @@ including ability to present channel and priority as visible log data</td>
<td valign="top">yes</td>
<td valign="top">not sure...</td>
</tr>
+<tr><td valign="top">native ability to send mail messages</td>
+<td valign="top">yes (<a href="ommail.html">ommail</a>, introduced in 3.17.0)</td>
+<td valign="top">not sure...</td>
+</tr>
<tr>
<td valign="top">good timestamp format control; at a
minimum, ISO 8601/RFC 3339 second-resolution UTC zone</td>
@@ -564,6 +578,6 @@ feature sheet. I have not yet been able to fully work through it. In
the mean time, you may want to read it in parallel. It is available at
<a href="http://www.balabit.com/network-security/syslog-ng/features/detailed/">Balabit's
site</a>.</p>
-<p>This document is current as of 2008-02-28 and definitely
+<p>This document is current as of 2008-04-08 and definitely
incomplete (I did not yet manage to complete it!).</p>
</body></html> \ No newline at end of file
diff --git a/doc/rsyslog_packages.html b/doc/rsyslog_packages.html
index 38c43c9..80ba96c 100644
--- a/doc/rsyslog_packages.html
+++ b/doc/rsyslog_packages.html
@@ -5,43 +5,72 @@
<body>
<h1>rsyslog packages</h1>
<p><b>Thanks to some volunteers, rsyslog is also available in package form on
-some distributions.</b> All available packages are listed below. If you would
+some distributions.</b> All currently known packages are listed below. If I have forgotten
+one or if you would
like to maintain a package for a new distribution, please mail me at
<a href="mailto:rgerhards@adiscon.com">rgerhards@adiscon.com</a>. Any help is *deeply*
appreciated. While I create the core daemon, the package maintainers are really
filling it with life, making it available to the average user. I am very
grateful for that!</p>
-<p>This list has last been updated on 2007-07-06 by
+<p>This list has last been updated on 2008-07-11 by
<a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a>.
New packages may appear at any time, so be sure to check this page whenever you
need a new one.</p>
-<p>Red Hat has recently begun to build RPMs for rsyslog. The URL changes, but a
-good place to look for them is at
-<a href="http://freshmeat.net/projects/rsyslog/">freshmeat's rsyslog info page</a>.
-Please note that the Red Hat RPMs do currently <b>not</b> include MySQL
-functionality. If you need that, you need to compile from the source tarball
-(which honestly is quite easy).</p>
-<h2>BSD</h2>
-<p>Give <a href="http://www.freshports.org/sysutils/rsyslog/">
-http://www.freshports.org/sysutils/rsyslog/</a> a try.</p>
-
-<h2>CentOS 4.3</h2>
-<a href="http://www.se-community.com/~james/rsyslog/">
-http://www.se-community.com/~james/rsyslog/</a></p>
-<p>Maintained by<b> James Bergamin.</b></p>
-
-<h2>openSUSE</h2>
-<a href="http://download.opensuse.org/repositories/home:/darix/">
-http://download.opensuse.org/repositories/home:/darix/</a></p>
-<p>Maintained by<b> darix</b></p>
-
-<h2>Almost any Linux</h2>
-<p><b>Bennet Todd</b> maintains packages that should work on almost any Linux.
+<ul>
+<li><b>BSD</b> (maintained by infofarmer)
+ <ul>
+ <li><a href="http://www.freshports.org/sysutils/rsyslog/"> http://www.freshports.org/sysutils/rsyslog/</a>
+ </ul>
+
+<li><b>CentOS 4.3</b> (maintained by James Bergamin)
+ <ul>
+ <li><a href="http://www.se-community.com/~james/rsyslog/">
+http://www.se-community.com/~james/rsyslog/</a>
+ </ul>
+
+<li><b>Debian</b> (maintained by Michael Biebl)
+ <ul>
+ <li><a href="http://packages.debian.org/sid/rsyslog">http://packages.debian.org/sid/rsyslog</a>
+ </ul>
+
+<li><b>Fedora</b>
+ <ul>
+ <li>Starting with Fedora 8, rsyslog is available as part of the core distribution.
+ </ul>
+
+<li><b>openSUSE</b> (maintained by darix)
+ <ul>
+ <li><a href="http://download.opensuse.org/repositories/home:/darix/">http://download.opensuse.org/repositories/home:/darix/</a>
+ </ul>
+
+<li><b>Red Hat Enterprise Linux</b>
+ <ul>
+ <li>Starting with RHEL 5.2, rsyslog is available as part of the core distribution.
+ </ul>
+
+<li><b>Ubuntu</b>
+ <ul>
+ <li>Starting with hardy, rsyslog is available from the universe repository.
+ </ul>
+
+<li>Almost any Linux</h2>
+ <ul>
+ <li>Bennet Todd maintains packages that should work on almost any Linux.
He keeps a current i386 tree. There is also a PPC tree, but that one is not paid
-much attention for (anyhow, it is known to typically work well, too).</p>
-<p>Please visit <a href="http://bent.latency.net/bent/">
+much attention for (anyhow, it is known to typically work well, too).
+Please visit <a href="http://bent.latency.net/bent/">
http://bent.latency.net/bent/</a>, select the relevant tree and then do a search
-for rsyslog.</p>
+for rsyslog.
+Please note, however, that as of this writing the versions in this repository
+have been aged a bit. So it may be worth trying to find some other places first.
+ </ul>
+</ul>
+
+<p>Just in case you are interested, the list of distribution is sorted by alphabetic order
+of the distribution name.
+<p>If you do not find a suitable package for your distribution, there is no reason
+to panic. It is quite simple to install rsyslog from the source tarball, so you
+should consider that.
</body>
</html>
diff --git a/doc/rsyslog_reliable_forwarding.html b/doc/rsyslog_reliable_forwarding.html
new file mode 100644
index 0000000..870ca9b
--- /dev/null
+++ b/doc/rsyslog_reliable_forwarding.html
@@ -0,0 +1,152 @@
+<html><head>
+<title>Reliable Forwarding of syslog Messages (via plain TCP syslog)</title>
+</head>
+<body>
+<h1>Reliable Forwarding of syslog Messages with Rsyslog</h1>
+ <P><small><i>Written by
+ <a href="http://www.gerhards.net/rainer">Rainer
+ Gerhards</a> (2008-06-27)</i></small></P>
+<h2>Abstract</h2>
+<p><i><b>In this paper, I describe how to forward
+<a href="http://www.monitorware.com/en/topics/syslog/">syslog</a>
+
+ messages (quite) reliable to a central rsyslog server.</b>
+This depends on rsyslog being installed on the client system and
+it is recommended to have it installed on the server system. Please note
+that industry-standard
+<a href="http://blog.gerhards.net/2008/04/on-unreliability-of-plain-tcp-syslog.html">plain TCP syslog protocol is not fully reliable</a>
+(thus the "quite reliable"). If you need a truely reliable solution, you need
+to look into RELP (natively supported by rsyslog).</i></p>
+
+<h2>The Intention</h2>
+<p>Whenever two systems talk over a network, something can go wrong.
+For example, the communications link may go down, or a client or server may abort.
+Even in regular cases, the server may be offline for a short period of time
+because of routine maintenance.
+<p>A logging system should be capable of avoiding message loss in situations where the
+server is not reachable. To do so, unsent data needs to be buffered at the client while the
+server is offline. Then, once the server is up again, this data is to be sent.
+<p>This can easily be acomplished by rsyslog. In rsyslog, every action runs on its own queue
+and each queue can be set to buffer data if the action is not ready. Of course,
+you must be able to detect that "the action is not ready", which means the remote
+server is offline. This can be detected with plain TCP syslog and RELP, but not with UDP.
+So you need to use either of the two. In this howto, we use plain TCP syslog.
+<p>Please note that we are using rsyslog-specific features. The are required on the
+client, but not on the server. So the client system must run rsyslog (at least version 3.12.0), while on the
+server another syslogd may be running, as long as it supports plain tcp syslog.
+<p><b>The rsyslog queueing subsystem tries to buffer to memory. So even if the
+remote server goes
+offline, no disk file is generated.</b> File on disk are created only if there is
+need to, for example if rsyslog runs out of (configured) memory queue space or needs
+to shutdown (and thus persist yet unsent messages). Using main memory and going to the
+disk when needed is a huge performance benefit. You do not need to care about it,
+because, all of it is handled automatically and transparently by rsyslog.</p>
+<h2>How To Setup</h2>
+<p>First, you need to create a working directory for rsyslog. This is where it
+stores its queue files (should need arise). You may use any location on your
+local system.
+<p>Next, you need to do is instruct rsyslog to use a
+disk queue and then configure your action. There is nothing else to do. With the
+following simple config file, you forward anything you receive to a remote server
+and have buffering applied automatically when it goes down. This must be done on the
+client machine.</p>
+<textarea rows="9" cols="80">
+$ModLoad imuxsock # local message reception
+
+$WorkDirectory /rsyslog/work # default location for work (spool) files
+
+$ActionQueueType LinkedList # use asynchronous processing
+$ActionQueueFileName srvrfwd # set file name, also enables disk mode
+$ActionResumeRetryCount -1 # infinite retries on insert failure
+$ActionQueueSaveOnShutdown on # save in-memory data if rsyslog shuts down
+*.* @@server:port
+</textarea>
+<p>The port given above is optional. It may not be specified, in which case you only
+provide the server name. The "$ActionQueueFileName" is used to create queue files, should need
+arise. This value must be unique inside rsyslog.conf. No two rules must use the same queue file.
+Also, for obvious reasons, it must only contain those characters that can be used inside a
+valid file name. Rsyslog possibly adds some characters in front and/or at the end of that name
+when it creates files. So that name should not be at the file size name length limit (which
+should not be a problem these days).
+<p>Please note that actual spool files are only created if the remote server is down
+<b>and</b> there is no more space in the in-memory queue. By default, a short failure
+of the remote server will never result in the creation of a disk file as a couple of
+hundered messages can be held in memory by default. [These parameters can be fine-tuned. However,
+then you need to either fully understand how the queue works
+(<a href="http://www.rsyslog.com/doc-queues.html">read elaborate doc</a>) or
+use <a href="http://www.rsyslog.com/doc-professional_support.html">professional services</a>
+to have it done based on
+your specs ;) - what that means is that fine-tuning queue parameters is far from
+being trivial...]
+<p>If you would like to test if your buffering scenario works, you need to
+stop, wait a while and restart you central server. Do <b>not</b> watch for files being created,
+as this usually does not happen and never happens immediately.
+
+<h3>Forwarding to More than One Server</h3>
+<p>If you have more than one server you would like to forward to, that's quickly done.
+Rsyslog has no limit on the number or type of actions, so you can define as many targets
+as you like. What is important to know, however, is that the full set of directives make
+up an action. So you can not simply add (just) a second forwarding rule, but need to
+duplicate the rule configuration as well. Be careful that you use different queue
+file names for the second action, else you will mess up your system.
+<p>A sample for forwarding to two hosts looks like this:
+<p>
+<textarea rows="20" cols="80">
+$ModLoad imuxsock.so # local message reception
+
+$WorkDirectory /rsyslog/work # default location for work (spool) files
+
+# start forwarding rule 1
+$ActionQueueType LinkedList # use asynchronous processing
+$ActionQueueFileName srvrfwd1 # set file name, also enables disk mode
+$ActionResumeRetryCount -1 # infinite retries on insert failure
+$ActionQueueSaveOnShutdown on # save in-memory data if rsyslog shuts down
+*.* @@server1:port
+# end forwarding rule 1
+
+# start forwarding rule 2
+$ActionQueueType LinkedList # use asynchronous processing
+$ActionQueueFileName srvrfwd2 # set file name, also enables disk mode
+$ActionResumeRetryCount -1 # infinite retries on insert failure
+$ActionQueueSaveOnShutdown on # save in-memory data if rsyslog shuts down
+*.* @@server2
+# end forwarding rule 2
+</textarea>
+<p>Note the filename used for the first rule it is "srvrfwd1" and for the second it
+is "srvrfwd2". I have used a server without port name in the second forwarding rule.
+This was just to illustrate how this can be done. You can also specify a port there
+(or drop the port from server1).
+<p>When there are multiple action queues, they all work independently. Thus, if server1
+goes down, server2 still receives data in real-time. The client will <b>not</b> block
+and wait for server1 to come back online. Similarily, server1's operation will not
+be affected by server2's state.
+
+<h2>Some Final Words on Reliability ...</h2>
+<p>Using plain TCP syslog provides a lot of reliability over UDP syslog. However,
+plain TCP syslog is <b>not</b> a fully reliable transport. In order to get full reliability,
+you need to use the RELP protocol.
+<p>Folow the next link to learn more about
+<a href="http://blog.gerhards.net/2008/04/on-unreliability-of-plain-tcp-syslog.html">the
+problems you may encounter with plain tcp syslog</a>.
+<h3>Feedback requested</h3>
+<P>I would appreciate feedback on this tutorial. If you have additional ideas,
+comments or find bugs (I *do* bugs - no way... ;)), please
+<a href="mailto:rgerhards@adiscon.com">let me know</a>.</P>
+<h2>Revision History</h2>
+<ul>
+ <li>2008-06-27 *
+ <a href="http://www.gerhards.net/rainer">Rainer Gerhards</a> * Initial Version created</li>
+</ul>
+<h2>Copyright</h2>
+<p>Copyright (c) 2008
+<a href="http://www.gerhards.net/rainer">Rainer Gerhards</a> and
+<a href="http://www.adiscon.com/en/">Adiscon</a>.</p>
+<p> Permission is granted to copy, distribute and/or modify this document
+ under the terms of the GNU Free Documentation License, Version 1.2
+ or any later version published by the Free Software Foundation;
+ with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+ Texts. A copy of the license can be viewed at
+<a href="http://www.gnu.org/copyleft/fdl.html">
+http://www.gnu.org/copyleft/fdl.html</a>.</p>
+</body>
+</html>
diff --git a/doc/status.html b/doc/status.html
new file mode 100644
index 0000000..63a3f58
--- /dev/null
+++ b/doc/status.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><title>rsyslog status page</title></head>
+<body>
+<h2>rsyslog status page</h2>
+<p>This page reflects the status as of 2008-04-15.</p>
+<h2>Current Releases</h2>
+
+<p><b>development:</b> 3.17.1 -
+<a href="http://www.rsyslog.com/Article213.phtml">change log</a> -
+<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-98.phtml">download</a>
+
+<br><b>beta:</b> 3.15.1 -
+<a href="http://www.rsyslog.com/Article210.phtml">change log</a> -
+<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-97.phtml">download</a></p>
+
+<p><b>v3 stable:</b> 3.14.2 - <a href="http://www.rsyslog.com/Article209.phtml">change log</a> -
+<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-96.phtml">download</a>
+
+<br><b>v2 stable:</b> 2.0.4 - <a href="http://www.rsyslog.com/Article197.phtml">change log</a> -
+<a href="http://www.rsyslog.com/Downloads-index-req-getit-lid-90.phtml">download</a>
+<br>v0 and v1 are deprecated and no longer supported. If you absolutely do not like to
+upgrade, you may consider purchasing a
+<a href="professional_support.html">commercial rsyslog support package</a>. Just let us point
+out that it is really not a good idea to still run a v0 version.
+
+<p><a href="v3compatibility.html">If you updgrade from version 2, be sure to read the rsyslog v3
+compatibility document.</a></p>
+<p>(<a href="version_naming.html">How are versions named?</a>)</p>
+
+<h2>Platforms</h2>
+<p>Thankfully, a number of folks have begin to build packages and
+help port rsyslog to other platforms. As such,
+<a href="http://wiki.rsyslog.com/index.php/Platforms">the
+platform list is now maintained inside the rsyslog wiki</a>.
+Platform maintainers perhaps have posted extra information there. If
+you do platform-specific work, feel free to add information to the wiki.</p>
+<p>Rsyslog is the default syslogd in Fedora 8 and above.</p>
+<h2>Additional information</h2>
+<p><b>Currently supported features are listed on the <a href="features.html">rsyslog features page</a>.</b></p>
+<ul>
+<li>The rsyslog home page is <a href="http://www.rsyslog.com">www.rsyslog.com</a>.</li>
+<li>Mailing list info can be found at <a href="http://lists.adiscon.net/mailman/listinfo/rsyslog">http://lists.adiscon.com/rsyslog</a>.</li>
+<li>The change log can be found at <a href="http://www.rsyslog.com/Topic4.phtml">
+http://www.rsyslog.com/Topic4.phtml</a>. </li>
+<li>Online documentation is available at <a href="http://www.rsyslog.com/doc">http://www.rsyslog.com/doc</a>.</li>
+<li>You may also find <a href="http://rgerhards.blogspot.com/">Rainer's blog</a>
+an interesting read.</li>
+</ul>
+<p>The project was initiated in 2003 and seriouosly begun in 2004 by
+<a href="http://www.gerhards.net/rainer">Rainer Gerhards</a>
+and is currently being maintained by him. See the <a href="history.html">history page</a> for more
+background information.</p>
+</body></html>
diff --git a/doc/troubleshoot.html b/doc/troubleshoot.html
new file mode 100644
index 0000000..f2e9206
--- /dev/null
+++ b/doc/troubleshoot.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><title>troubleshooting rsyslog</title></head>
+<body>
+<h2>troubleshooting rsyslog</h2>
+<p><b>Having trouble with <a href="http://www.rsyslog.com">rsyslog</a>?</b>
+This page provides some tips on where to look for help and what to do
+if you need to ask for assistance. This page is continously being expanded.
+<p>Useful troublehshooting ressources are:
+<ul>
+<li>The <a href="http://www.rsyslog.com/doc">rsyslog documentation</a> - note that the online version always covers
+the most recent development version. However, there is a version-specific
+doc set in each tarball. If you installed rsyslog from a package, there usually
+is a rsyslog-doc package, that often needs to be installed separately.
+<li>The <a href="http://wiki.rsyslog.com">rsyslog wiki</a> provides user tips and experiences.
+</ul>
+<p><b>Asking for Help</b>
+<p>If you can't find the answer yourself, you should look at these places for
+community help.
+<ul>
+<li>The <a href="http://kb.monitorware.com/rsyslog-f40.html">rsyslog forum</a>. This is
+the preferred method of obtaining support.
+<li>The <a href="http://lists.adiscon.net/mailman/listinfo/rsyslog">rsyslog mailing list</a>.
+This is a low-volume list which occasional gets traffic spikes.
+The mailing list is probably a good place for complex questions.
+</ul>
+<p>[<a href="manual.html">manual index</a>]
+[<a href="http://www.rsyslog.com/">rsyslog site</a>]</p>
+<p><font size="2">This documentation is part of the
+<a href="http://www.rsyslog.com/">rsyslog</a> project.<br>
+Copyright &copy; 2008 by <a href="http://www.gerhards.net/rainer">Rainer Gerhards</a> and
+<a href="http://www.adiscon.com/">Adiscon</a>. Released under the GNU GPL
+version 2 or higher.</font></p>
+</body>
+</html>
+
diff --git a/expr.c b/expr.c
index 0f6e746..736b9d1 100644
--- a/expr.c
+++ b/expr.c
@@ -114,7 +114,7 @@ terminal(expr_t *pThis, ctok_t *tok)
finalize_it:
if(pToken != NULL) {
- CHKiRet(ctok_token.Destruct(&pToken)); /* "eat" processed token */
+ ctok_token.Destruct(&pToken); /* "eat" processed token */
}
RETiRet;
@@ -336,7 +336,7 @@ ENDobjConstruct(expr)
/* ConstructionFinalizer
* rgerhards, 2008-01-09
*/
-rsRetVal exprConstructFinalize(expr_t *pThis)
+rsRetVal exprConstructFinalize(expr_t __attribute__((unused)) *pThis)
{
DEFiRet;
diff --git a/glbl.h b/glbl.h
index fb55fb7..6d08ddd 100644
--- a/glbl.h
+++ b/glbl.h
@@ -33,6 +33,7 @@
#define glblGetIOBufSize() 4096 /* size of the IO buffer, e.g. for strm class */
+extern uchar *glblModPath; /* module load path */
extern uchar *pszWorkDir;
#define glblGetWorkDir() (pszWorkDir == NULL ? (uchar*) "" : pszWorkDir)
diff --git a/modules.c b/modules.c
index 57df48b..32a71c0 100644
--- a/modules.c
+++ b/modules.c
@@ -39,6 +39,9 @@
#include <time.h>
#include <assert.h>
#include <errno.h>
+#ifdef OS_BSD
+# include "libgen.h"
+#endif
#include <dlfcn.h> /* TODO: replace this with the libtools equivalent! */
@@ -780,6 +783,17 @@ BEGINAbstractObjClassInit(module, 1, OBJ_IS_CORE_MODULE) /* class, version - CHA
SetModDir(pModPath);
}
+ /* now check if another module path was set via the command line (-M)
+ * if so, that overrides the environment. Please note that we must use
+ * a global setting here because the command line parser can NOT call
+ * into the module object, because it is not initialized at that point. So
+ * instead a global setting is changed and we pick it up as soon as we
+ * initialize -- rgerhards, 2008-04-04
+ */
+ if(glblModPath != NULL) {
+ SetModDir(glblModPath);
+ }
+
/* request objects we use */
CHKiRet(objUse(errmsg, CORE_COMPONENT));
ENDObjClassInit(module)
diff --git a/msg.c b/msg.c
index 7c020a6..bd1e425 100644
--- a/msg.c
+++ b/msg.c
@@ -159,14 +159,40 @@ static void MsgLockingDummy(msg_t __attribute__((unused)) *pMsg)
* where a message may be accessed by multiple threads. This implementation here
* is the version for multiple concurrent acces. It initializes the locking
* structures.
+ * TODO: change to an iRet interface! -- rgerhards, 2008-07-14
*/
static void MsgPrepareEnqueueLockingCase(msg_t *pThis)
{
+ int iErr;
+ BEGINfunc
assert(pThis != NULL);
- pthread_mutexattr_settype(&pThis->mutAttr, PTHREAD_MUTEX_RECURSIVE);
+ iErr = pthread_mutexattr_init(&pThis->mutAttr);
+ if(iErr != 0) {
+ dbgprintf("error initializing mutex attribute in %s:%d, trying to continue\n",
+ __FILE__, __LINE__);
+ }
+ iErr = pthread_mutexattr_settype(&pThis->mutAttr, PTHREAD_MUTEX_RECURSIVE);
+ if(iErr != 0) {
+ dbgprintf("ERROR setting mutex attribute to recursive in %s:%d, trying to continue "
+ "but we will probably either abort or hang soon\n",
+ __FILE__, __LINE__);
+ /* TODO: it makes very little sense to continue here,
+ * but it requires an iRet interface to gracefully shut
+ * down. We should do that over time. -- rgerhards, 2008-07-14
+ */
+ }
pthread_mutex_init(&pThis->mut, &pThis->mutAttr);
+
+ /* we do no longer need the attribute. According to the
+ * POSIX spec, we can destroy it without affecting the
+ * initialized mutex (that used the attribute).
+ * rgerhards, 2008-07-14
+ */
+ pthread_mutexattr_destroy(&pThis->mutAttr);
+ ENDfunc
}
+
/* ... and now the locking and unlocking implementations: */
static void MsgLockLockingCase(msg_t *pThis)
{
@@ -201,11 +227,12 @@ static void MsgDeleteMutexLockingCase(msg_t *pThis)
*/
rsRetVal MsgEnableThreadSafety(void)
{
+ DEFiRet;
funcLock = MsgLockLockingCase;
funcUnlock = MsgUnlockLockingCase;
funcMsgPrepareEnqueue = MsgPrepareEnqueueLockingCase;
funcDeleteMutex = MsgDeleteMutexLockingCase;
- return RS_RET_OK;
+ RETiRet;
}
/* end locking functions */
@@ -646,19 +673,23 @@ char *getMSG(msg_t *pM)
/* Get PRI value in text form */
char *getPRI(msg_t *pM)
{
+ int pri;
+
if(pM == NULL)
return "";
MsgLock(pM);
if(pM->pszPRI == NULL) {
- /* OK, we need to construct it...
- * we use a 5 byte buffer - as of
- * RFC 3164, it can't be longer. Should it
- * still be, snprintf will truncate...
+ /* OK, we need to construct it... we use a 5 byte buffer - as of
+ * RFC 3164, it can't be longer. Should it still be, snprintf will truncate...
+ * Note that we do not use the LOG_MAKEPRI macro. This macro
+ * is a simple add of the two values under FreeBSD 7. So we implement
+ * the logic in our own code. This is a change from a bug
+ * report. -- rgerhards, 2008-07-14
*/
+ pri = pM->iFacility * 8 + pM->iSeverity;
if((pM->pszPRI = malloc(5)) == NULL) return "";
- pM->iLenPRI = snprintf((char*)pM->pszPRI, 5, "%d",
- LOG_MAKEPRI(pM->iFacility, pM->iSeverity));
+ pM->iLenPRI = snprintf((char*)pM->pszPRI, 5, "%d", pri);
}
MsgUnlock(pM);
@@ -1604,20 +1635,17 @@ char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
pRes = getMSG(pMsg);
} else if(!strcmp((char*) pName, "rawmsg")) {
pRes = getRawMsg(pMsg);
- } else if(!strcmp((char*) pName, "UxTradMsg")) {
+ } else if(!strcmp((char*) pName, "uxtradmsg")) {
pRes = getUxTradMsg(pMsg);
- } else if( !strcmp((char*) pName, "FROMHOST")
- || !strcmp((char*) pName, "fromhost")) {
+ } else if(!strcmp((char*) pName, "fromhost")) {
pRes = getRcvFrom(pMsg);
- } else if(!strcmp((char*) pName, "source")
- || !strcmp((char*) pName, "hostname")
- || !strcmp((char*) pName, "HOSTNAME")) {
+ } else if(!strcmp((char*) pName, "source") || !strcmp((char*) pName, "hostname")) {
pRes = getHOSTNAME(pMsg);
} else if(!strcmp((char*) pName, "syslogtag")) {
pRes = getTAG(pMsg);
- } else if(!strcmp((char*) pName, "PRI")) {
+ } else if(!strcmp((char*) pName, "pri")) {
pRes = getPRI(pMsg);
- } else if(!strcmp((char*) pName, "PRI-text")) {
+ } else if(!strcmp((char*) pName, "pri-text")) {
pBuf = malloc(20 * sizeof(char));
if(pBuf == NULL) {
*pbMustBeFreed = 0;
@@ -1639,57 +1667,57 @@ char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
} else if(!strcmp((char*) pName, "timegenerated")) {
pRes = getTimeGenerated(pMsg, pTpe->data.field.eDateFormat);
} else if(!strcmp((char*) pName, "timereported")
- || !strcmp((char*) pName, "TIMESTAMP")) {
+ || !strcmp((char*) pName, "timestamp")) {
pRes = getTimeReported(pMsg, pTpe->data.field.eDateFormat);
} else if(!strcmp((char*) pName, "programname")) {
pRes = getProgramName(pMsg);
- } else if(!strcmp((char*) pName, "PROTOCOL-VERSION")) {
+ } else if(!strcmp((char*) pName, "protocol-version")) {
pRes = getProtocolVersionString(pMsg);
- } else if(!strcmp((char*) pName, "STRUCTURED-DATA")) {
+ } else if(!strcmp((char*) pName, "structured-data")) {
pRes = getStructuredData(pMsg);
- } else if(!strcmp((char*) pName, "APP-NAME")) {
+ } else if(!strcmp((char*) pName, "app-name")) {
pRes = getAPPNAME(pMsg);
- } else if(!strcmp((char*) pName, "PROCID")) {
+ } else if(!strcmp((char*) pName, "procid")) {
pRes = getPROCID(pMsg);
- } else if(!strcmp((char*) pName, "MSGID")) {
+ } else if(!strcmp((char*) pName, "msgid")) {
pRes = getMSGID(pMsg);
/* here start system properties (those, that do not relate to the message itself */
- } else if(!strcmp((char*) pName, "$NOW")) {
+ } else if(!strcmp((char*) pName, "$now")) {
if((pRes = (char*) getNOW(NOW_NOW)) == NULL) {
return "***OUT OF MEMORY***";
} else
*pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
- } else if(!strcmp((char*) pName, "$YEAR")) {
+ } else if(!strcmp((char*) pName, "$year")) {
if((pRes = (char*) getNOW(NOW_YEAR)) == NULL) {
return "***OUT OF MEMORY***";
} else
*pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
- } else if(!strcmp((char*) pName, "$MONTH")) {
+ } else if(!strcmp((char*) pName, "$month")) {
if((pRes = (char*) getNOW(NOW_MONTH)) == NULL) {
return "***OUT OF MEMORY***";
} else
*pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
- } else if(!strcmp((char*) pName, "$DAY")) {
+ } else if(!strcmp((char*) pName, "$day")) {
if((pRes = (char*) getNOW(NOW_DAY)) == NULL) {
return "***OUT OF MEMORY***";
} else
*pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
- } else if(!strcmp((char*) pName, "$HOUR")) {
+ } else if(!strcmp((char*) pName, "$hour")) {
if((pRes = (char*) getNOW(NOW_HOUR)) == NULL) {
return "***OUT OF MEMORY***";
} else
*pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
- } else if(!strcmp((char*) pName, "$HHOUR")) {
+ } else if(!strcmp((char*) pName, "$hhour")) {
if((pRes = (char*) getNOW(NOW_HHOUR)) == NULL) {
return "***OUT OF MEMORY***";
} else
*pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
- } else if(!strcmp((char*) pName, "$QHOUR")) {
+ } else if(!strcmp((char*) pName, "$qhour")) {
if((pRes = (char*) getNOW(NOW_QHOUR)) == NULL) {
return "***OUT OF MEMORY***";
} else
*pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
- } else if(!strcmp((char*) pName, "$MINUTE")) {
+ } else if(!strcmp((char*) pName, "$minute")) {
if((pRes = (char*) getNOW(NOW_MINUTE)) == NULL) {
return "***OUT OF MEMORY***";
} else
@@ -1698,6 +1726,7 @@ char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
/* there is no point in continuing, we may even otherwise render the
* error message unreadable. rgerhards, 2007-07-10
*/
+ dbgprintf("invalid property name: '%s'\n", pName);
return "**INVALID PROPERTY NAME**";
}
@@ -1868,6 +1897,32 @@ char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
#endif /* #ifdef FEATURE_REGEXP */
}
+ /* now check if we need to do our "SP if first char is non-space" hack logic */
+ if(*pRes && pTpe->data.field.options.bSPIffNo1stSP) {
+ char *pB;
+ uchar cFirst = *pRes;
+
+ /* here, we always destruct the buffer and return a new one */
+ pB = (char *) malloc(2 * sizeof(char));
+ if(pB == NULL) {
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ *pbMustBeFreed = 0;
+ return "**OUT OF MEMORY**";
+ }
+ pRes = pB;
+ *pbMustBeFreed = 1;
+
+ if(cFirst == ' ') {
+ /* if we have a SP, we must return an empty string */
+ *pRes = '\0'; /* empty */
+ } else {
+ /* if it is no SP, we need to return one */
+ *pRes = ' ';
+ *(pRes+1) = '\0';
+ }
+ }
+
if(*pRes) {
/* case conversations (should go after substring, because so we are able to
* work on the smallest possible buffer).
diff --git a/net.c b/net.c
index ab66932..bbd6bec 100644
--- a/net.c
+++ b/net.c
@@ -580,7 +580,7 @@ static int isAllowedSender(struct AllowedSenders *pAllowRoot, struct sockaddr *p
static int
should_use_so_bsdcompat(void)
{
-#ifndef BSD
+#ifndef OS_BSD
static int init_done;
static int so_bsdcompat_is_obsolete;
@@ -608,9 +608,9 @@ should_use_so_bsdcompat(void)
so_bsdcompat_is_obsolete = 1;
}
return !so_bsdcompat_is_obsolete;
-#else /* #ifndef BSD */
+#else /* #ifndef OS_BSD */
return 1;
-#endif /* #ifndef BSD */
+#endif /* #ifndef OS_BSD */
}
#ifndef SO_BSDCOMPAT
/* this shall prevent compiler errors due to undfined name */
@@ -852,6 +852,44 @@ finalize_it:
}
+/* get the name of the local host. A pointer to a character pointer is passed
+ * in, which on exit points to the local hostname. This buffer is dynamically
+ * allocated and must be free()ed by the caller. If the functions returns an
+ * error, the pointer is NULL. This function is based on GNU/Hurd's localhostname
+ * function.
+ * rgerhards, 20080-04-10
+ */
+static rsRetVal
+getLocalHostname(uchar **ppName)
+{
+ DEFiRet;
+ uchar *buf = NULL;
+ size_t buf_len = 0;
+
+ assert(ppName != NULL);
+
+ do {
+ if(buf == NULL) {
+ buf_len = 128; /* Initial guess */
+ CHKmalloc(buf = malloc(buf_len));
+ } else {
+ buf_len += buf_len;
+ CHKmalloc(buf = realloc (buf, buf_len));
+ }
+ } while((gethostname((char*)buf, buf_len) == 0 && !memchr (buf, '\0', buf_len)) || errno == ENAMETOOLONG);
+
+ *ppName = buf;
+ buf = NULL;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(buf != NULL)
+ free(buf);
+ }
+ RETiRet;
+}
+
+
/* closes the UDP listen sockets (if they exist) and frees
* all dynamically assigned memory.
*/
@@ -948,7 +986,7 @@ int *create_udp_socket(uchar *hostname, uchar *pszPort, int bIsServer)
/* We need to enable BSD compatibility. Otherwise an attacker
* could flood our log files by sending us tons of ICMP errors.
*/
-#if !defined(BSD) && !defined(__hpux)
+#if !defined(OS_BSD) && !defined(__hpux)
if (should_use_so_bsdcompat()) {
if (setsockopt(*s, SOL_SOCKET, SO_BSDCOMPAT,
(char *) &on, sizeof(on)) < 0) {
@@ -1047,6 +1085,7 @@ CODESTARTobjQueryInterface(net)
pIf->closeUDPListenSockets = closeUDPListenSockets;
pIf->isAllowedSender = isAllowedSender;
pIf->should_use_so_bsdcompat = should_use_so_bsdcompat;
+ pIf->getLocalHostname = getLocalHostname;
finalize_it:
ENDobjQueryInterface(net)
diff --git a/net.h b/net.h
index 2004dcf..0f5b0bc 100644
--- a/net.h
+++ b/net.h
@@ -34,7 +34,7 @@
#define ADDR_NAME 0x01 /* address is hostname wildcard) */
#define ADDR_PRI6 0x02 /* use IPv6 address prior to IPv4 when resolving */
-#ifdef BSD
+#ifdef OS_BSD
# ifndef _KERNEL
# define s6_addr32 __u6_addr.__u6_addr32
# endif
@@ -97,6 +97,7 @@ BEGINinterface(net) /* name must also be changed in ENDinterface macro! */
int *(*create_udp_socket)(uchar *hostname, uchar *LogPort, int bIsServer);
void (*closeUDPListenSockets)(int *finet);
int (*isAllowedSender)(struct AllowedSenders *pAllowRoot, struct sockaddr *pFrom, const char *pszFromHost);
+ rsRetVal (*getLocalHostname)(uchar**);
int (*should_use_so_bsdcompat)(void);
/* data memebers - these should go away over time... TODO */
int *pACLAddHostnameOnFail; /* add hostname to acl when DNS resolving has failed */
@@ -105,7 +106,7 @@ BEGINinterface(net) /* name must also be changed in ENDinterface macro! */
struct AllowedSenders *pAllowedSenders_TCP;
struct AllowedSenders *pAllowedSenders_GSS;
ENDinterface(net)
-#define netCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
+#define netCURR_IF_VERSION 2 /* increment whenever you change the interface structure! */
/* prototypes */
PROTOTYPEObj(net);
diff --git a/obj-types.h b/obj-types.h
index afbe1a8..4cd4515 100644
--- a/obj-types.h
+++ b/obj-types.h
@@ -210,7 +210,7 @@ rsRetVal objName##ClassExit(void) \
#define CODESTARTObjClassExit(objName)
#define ENDObjClassExit(objName) \
- iRet = obj.UnregisterObj((uchar*)#objName, pObjInfoOBJ); \
+ iRet = obj.UnregisterObj((uchar*)#objName); \
RETiRet; \
}
diff --git a/obj.c b/obj.c
index bb907d4..7a4435e 100644
--- a/obj.c
+++ b/obj.c
@@ -1074,7 +1074,7 @@ RegisterObj(uchar *pszObjName, objInfo_t *pInfo)
if(i >= OBJ_NUM_IDS) ABORT_FINALIZE(RS_RET_OBJ_REGISTRY_OUT_OF_SPACE);
arrObjInfo[i] = pInfo;
- dbgprintf("object '%s' successfully registered with index %d, qIF %p\n", pszObjName, i, pInfo->QueryIF);
+ /* DEV debug only: dbgprintf("object '%s' successfully registered with index %d, qIF %p\n", pszObjName, i, pInfo->QueryIF); */
finalize_it:
if(iRet != RS_RET_OK) {
@@ -1090,14 +1090,13 @@ finalize_it:
* rgerhards, 2008-03-10
*/
static rsRetVal
-UnregisterObj(uchar *pszObjName, objInfo_t *pInfo)
+UnregisterObj(uchar *pszObjName)
{
DEFiRet;
int bFound;
int i;
assert(pszObjName != NULL);
- assert(pInfo != NULL);
bFound = 0;
i = 0;
@@ -1114,7 +1113,7 @@ UnregisterObj(uchar *pszObjName, objInfo_t *pInfo)
ABORT_FINALIZE(RS_RET_OBJ_NOT_REGISTERED);
InfoDestruct(&arrObjInfo[i]);
- dbgprintf("object '%s' successfully unregistered with index %d\n", pszObjName, i);
+ /* DEV debug only: dbgprintf("object '%s' successfully unregistered with index %d\n", pszObjName, i); */
finalize_it:
if(iRet != RS_RET_OK) {
@@ -1138,7 +1137,7 @@ UseObj(char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf)
objInfo_t *pObjInfo;
- dbgprintf("source file %s requests object '%s', ifIsLoaded %d\n", srcFile, pObjName, pIf->ifIsLoaded);
+ /* DEV debug only: dbgprintf("source file %s requests object '%s', ifIsLoaded %d\n", srcFile, pObjName, pIf->ifIsLoaded); */
if(pIf->ifIsLoaded == 1) {
ABORT_FINALIZE(RS_RET_OK); /* we are already set */
@@ -1171,7 +1170,6 @@ UseObj(char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf)
}
/* if we reach this point, we have a valid pObjInfo */
- //if(pObjInfo->pModInfo != NULL) { /* NULL means core module */
if(pObjFile != NULL) { /* NULL means core module */
module.Use(srcFile, pObjInfo->pModInfo); /* increase refcount */
}
diff --git a/obj.h b/obj.h
index 87c6c91..29ad2ae 100644
--- a/obj.h
+++ b/obj.h
@@ -104,13 +104,13 @@ BEGINinterface(obj) /* name must also be changed in ENDinterface macro! */
rsRetVal (*SerializeProp)(strm_t *pStrm, uchar *pszPropName, propType_t propType, void *pUsr);
rsRetVal (*EndSerialize)(strm_t *pStrm);
rsRetVal (*RegisterObj)(uchar *pszObjName, objInfo_t *pInfo);
- rsRetVal (*UnregisterObj)(uchar *pszObjName, objInfo_t *pInfo);
+ rsRetVal (*UnregisterObj)(uchar *pszObjName);
rsRetVal (*Deserialize)(void *ppObj, uchar *pszTypeExpected, strm_t *pStrm, rsRetVal (*fFixup)(obj_t*,void*), void *pUsr);
rsRetVal (*DeserializePropBag)(obj_t *pObj, strm_t *pStrm);
rsRetVal (*SetName)(obj_t *pThis, uchar *pszName);
uchar * (*GetName)(obj_t *pThis);
ENDinterface(obj)
-#define objCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
+#define objCURR_IF_VERSION 2 /* increment whenever you change the interface structure! */
/* prototypes */
diff --git a/omfwd.c b/omfwd.c
index 19d0937..dfa9b98 100644
--- a/omfwd.c
+++ b/omfwd.c
@@ -71,7 +71,7 @@ DEFobjCurrIf(net)
DEFobjCurrIf(tcpclt)
typedef struct _instanceData {
- char f_hname[MAXHOSTNAMELEN+1];
+ char *f_hname;
short sock; /* file descriptor */
int *pSockArray; /* sockets to use for UDP */
enum { /* TODO: we shoud revisit these definitions */
@@ -145,6 +145,9 @@ CODESTARTfreeInstance
tcpclt.Destruct(&pData->pTCPClt);
}
+ if(pData->f_hname != NULL)
+ free(pData->f_hname);
+
ENDfreeInstance
@@ -499,7 +502,7 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1)
/* extract the host first (we do a trick - we replace the ';' or ':' with a '\0')
* now skip to port and then template name. rgerhards 2005-07-06
*/
- for(q = p ; *p && *p != ';' && *p != ':' ; ++p)
+ for(q = p ; *p && *p != ';' && *p != ':' && *p != '#' ; ++p)
/* JUST SKIP */;
pData->port = NULL;
@@ -525,29 +528,22 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1)
/* now skip to template */
bErr = 0;
- while(*p && *p != ';') {
- if(*p && *p != ';' && !isspace((int) *p)) {
- if(bErr == 0) { /* only 1 error msg! */
- bErr = 1;
- errno = 0;
- errmsg.LogError(NO_ERRCODE, "invalid selector line (port), probably not doing "
- "what was intended");
- }
- }
- ++p;
- }
-
+ while(*p && *p != ';' && *p != '#' && !isspace((int) *p))
+ ++p; /*JUST SKIP*/
+
/* TODO: make this if go away! */
- if(*p == ';') {
+ if(*p == ';' || *p == '#' || isspace(*p)) {
+ uchar cTmp = *p;
*p = '\0'; /* trick to obtain hostname (later)! */
- strcpy(pData->f_hname, (char*) q);
- *p = ';';
- } else
- strcpy(pData->f_hname, (char*) q);
+ CHKmalloc(pData->f_hname = strdup((char*) q));
+ *p = cTmp;
+ } else {
+ CHKmalloc(pData->f_hname = strdup((char*) q));
+ }
/* process template */
CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS,
- (pszTplName == NULL) ? (uchar*)"RSYSLOG_TraditionalForwardFormat" : pszTplName));
+ (pszTplName == NULL) ? (uchar*)"RSYSLOG_TraditionalForwardFormat" : pszTplName));
/* first set the pData->eDestState */
memset(&hints, 0, sizeof(hints));
@@ -562,8 +558,7 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1)
pData->eDestState = eDestFORW;
pData->f_addr = res;
}
- /*
- * Otherwise the host might be unknown due to an
+ /* Otherwise the host might be unknown due to an
* inaccessible nameserver (perhaps on the same
* host). We try to get the ip number later, like
* FORW_SUSP.
diff --git a/omusrmsg.c b/omusrmsg.c
index c400814..42d3291 100644
--- a/omusrmsg.c
+++ b/omusrmsg.c
@@ -119,7 +119,7 @@ static void endtty()
* BSD because they are not available there. We only emulate what we actually
* need! rgerhards 2005-03-18
*/
-#ifdef BSD
+#ifdef OS_BSD
static FILE *BSD_uf = NULL;
void setutent(void)
{
@@ -145,7 +145,7 @@ void endutent(void)
fclose(BSD_uf);
BSD_uf = NULL;
}
-#endif
+#endif /* #ifdef OS_BSD */
/*
@@ -209,7 +209,7 @@ static rsRetVal wallmsg(uchar* pMsg, instanceData *pData)
/* is this slot used? */
if (ut.ut_name[0] == '\0')
continue;
-#ifndef BSD
+#ifndef OS_BSD
if (ut.ut_type != USER_PROCESS)
continue;
#endif
diff --git a/outchannel.c b/outchannel.c
index 394371f..d013ea0 100644
--- a/outchannel.c
+++ b/outchannel.c
@@ -91,12 +91,12 @@ static void skip_Comma(char **pp)
/* helper to ochAddLine. Parses a comma-delimited field
* The field is delimited by SP or comma. Leading whitespace
* is "eaten" and does not become part of the field content.
- * returns: 0 - ok, 1 - failure
*/
-static int get_Field(uchar **pp, uchar **pField)
+static rsRetVal get_Field(uchar **pp, uchar **pField)
{
+ DEFiRet;
register uchar *p;
- cstr_t *pStrB;
+ cstr_t *pStrB = NULL;
assert(pp != NULL);
assert(*pp != NULL);
@@ -105,21 +105,25 @@ static int get_Field(uchar **pp, uchar **pField)
skip_Comma((char**)pp);
p = *pp;
- if(rsCStrConstruct(&pStrB) != RS_RET_OK)
- return 1;
+ CHKiRet(rsCStrConstruct(&pStrB));
rsCStrSetAllocIncrement(pStrB, 32);
/* copy the field */
while(*p && *p != ' ' && *p != ',') {
- rsCStrAppendChar(pStrB, *p++);
+ CHKiRet(rsCStrAppendChar(pStrB, *p++));
}
*pp = p;
- rsCStrFinish(pStrB);
- if(rsCStrConvSzStrAndDestruct(pStrB, pField, 0) != RS_RET_OK)
- return 1;
+ CHKiRet(rsCStrFinish(pStrB));
+ CHKiRet(rsCStrConvSzStrAndDestruct(pStrB, pField, 0));
- return 0;
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pStrB != NULL)
+ rsCStrDestruct(&pStrB);
+ }
+
+ RETiRet;
}
@@ -156,12 +160,12 @@ static int get_off_t(uchar **pp, off_t *pOff_t)
* current position to the end of line and returns it
* to the caller. Leading white space is removed, but
* not trailing.
- * returns: 0 - ok, 1 - failure
*/
-static inline int get_restOfLine(uchar **pp, uchar **pBuf)
+static inline rsRetVal get_restOfLine(uchar **pp, uchar **pBuf)
{
+ DEFiRet;
register uchar *p;
- cstr_t *pStrB;
+ cstr_t *pStrB = NULL;
assert(pp != NULL);
assert(*pp != NULL);
@@ -170,21 +174,25 @@ static inline int get_restOfLine(uchar **pp, uchar **pBuf)
skip_Comma((char**)pp);
p = *pp;
- if(rsCStrConstruct(&pStrB) != RS_RET_OK)
- return 1;
+ CHKiRet(rsCStrConstruct(&pStrB));
rsCStrSetAllocIncrement(pStrB, 32);
/* copy the field */
while(*p) {
- rsCStrAppendChar(pStrB, *p++);
+ CHKiRet(rsCStrAppendChar(pStrB, *p++));
}
*pp = p;
- rsCStrFinish(pStrB);
- if(rsCStrConvSzStrAndDestruct(pStrB, pBuf, 0) != RS_RET_OK)
- return 1;
+ CHKiRet(rsCStrFinish(pStrB));
+ CHKiRet(rsCStrConvSzStrAndDestruct(pStrB, pBuf, 0));
- return 0;
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pStrB != NULL)
+ rsCStrDestruct(&pStrB);
+ }
+
+ RETiRet;
}
@@ -291,6 +299,5 @@ void ochPrintList(void)
pOch = pOch->pNext; /* done, go next */
}
}
-/*
- * vi:set ai:
+/* vi:set ai:
*/
diff --git a/parse.c b/parse.c
index bca6457..171e535 100644
--- a/parse.c
+++ b/parse.c
@@ -235,15 +235,16 @@ rsRetVal parsSkipWhitespace(rsParsObj *pThis)
* 0 means "no", 1 "yes"
* - bTrimLeading
* - bTrimTrailing
+ * - bConvLower - convert string to lower case?
*
* Output:
* ppCStr Pointer to the parsed string - must be freed by caller!
*/
-rsRetVal parsDelimCStr(rsParsObj *pThis, cstr_t **ppCStr, char cDelim, int bTrimLeading, int bTrimTrailing)
+rsRetVal parsDelimCStr(rsParsObj *pThis, cstr_t **ppCStr, char cDelim, int bTrimLeading, int bTrimTrailing, int bConvLower)
{
DEFiRet;
register unsigned char *pC;
- cstr_t *pCStr;
+ cstr_t *pCStr = NULL;
rsCHECKVALIDOBJECT(pThis, OIDrsPars);
@@ -254,12 +255,8 @@ rsRetVal parsDelimCStr(rsParsObj *pThis, cstr_t **ppCStr, char cDelim, int bTrim
pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos;
- while(pThis->iCurrPos < rsCStrLen(pThis->pCStr)
- && *pC != cDelim) {
- if((iRet = rsCStrAppendChar(pCStr, *pC)) != RS_RET_OK) {
- rsCStrDestruct(&pCStr);
- FINALIZE;
- }
+ while(pThis->iCurrPos < rsCStrLen(pThis->pCStr) && *pC != cDelim) {
+ CHKiRet(rsCStrAppendChar(pCStr, bConvLower ? tolower(*pC) : *pC));
++pThis->iCurrPos;
++pC;
}
@@ -271,22 +268,21 @@ rsRetVal parsDelimCStr(rsParsObj *pThis, cstr_t **ppCStr, char cDelim, int bTrim
/* We got the string, now take it and see if we need to
* remove anything at its end.
*/
- if((iRet = rsCStrFinish(pCStr)) != RS_RET_OK) {
- rsCStrDestruct (&pCStr);
- FINALIZE;
- }
+ CHKiRet(rsCStrFinish(pCStr));
if(bTrimTrailing) {
- if((iRet = rsCStrTrimTrailingWhiteSpace(pCStr))
- != RS_RET_OK) {
- rsCStrDestruct (&pCStr);
- FINALIZE;
- }
+ CHKiRet(rsCStrTrimTrailingWhiteSpace(pCStr));
}
/* done! */
*ppCStr = pCStr;
+
finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pCStr != NULL)
+ rsCStrDestruct(&pCStr);
+ }
+
RETiRet;
}
@@ -308,13 +304,12 @@ finalize_it:
rsRetVal parsQuotedCStr(rsParsObj *pThis, cstr_t **ppCStr)
{
register unsigned char *pC;
- cstr_t *pCStr;
+ cstr_t *pCStr = NULL;
DEFiRet;
rsCHECKVALIDOBJECT(pThis, OIDrsPars);
- if((iRet = parsSkipAfterChar(pThis, '"')) != RS_RET_OK)
- FINALIZE;
+ CHKiRet(parsSkipAfterChar(pThis, '"'));
pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos;
/* OK, we most probably can obtain a value... */
@@ -331,16 +326,10 @@ rsRetVal parsQuotedCStr(rsParsObj *pThis, cstr_t **ppCStr)
* to the output buffer (but do not rely on this,
* we might later introduce other things, like \007!
*/
- if((iRet = rsCStrAppendChar(pCStr, *pC)) != RS_RET_OK) {
- rsCStrDestruct(&pCStr);
- FINALIZE;
- }
+ CHKiRet(rsCStrAppendChar(pCStr, *pC));
}
} else { /* regular character */
- if((iRet = rsCStrAppendChar(pCStr, *pC)) != RS_RET_OK) {
- rsCStrDestruct (&pCStr);
- FINALIZE;
- }
+ CHKiRet(rsCStrAppendChar(pCStr, *pC));
}
++pThis->iCurrPos;
++pC;
@@ -350,19 +339,22 @@ rsRetVal parsQuotedCStr(rsParsObj *pThis, cstr_t **ppCStr)
++pThis->iCurrPos; /* 'eat' trailing quote */
} else {
/* error - improperly quoted string! */
- rsCStrDestruct (&pCStr);
+ rsCStrDestruct(&pCStr);
ABORT_FINALIZE(RS_RET_MISSING_TRAIL_QUOTE);
}
/* We got the string, let's finish it... */
- if((iRet = rsCStrFinish(pCStr)) != RS_RET_OK) {
- rsCStrDestruct (&pCStr);
- FINALIZE;
- }
+ CHKiRet(rsCStrFinish(pCStr));
/* done! */
*ppCStr = pCStr;
+
finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pCStr != NULL)
+ rsCStrDestruct(&pCStr);
+ }
+
RETiRet;
}
diff --git a/parse.h b/parse.h
index 483c109..b7ac950 100644
--- a/parse.h
+++ b/parse.h
@@ -91,7 +91,7 @@ rsRetVal parsSkipWhitespace(rsParsObj *pThis);
* Output:
* ppCStr Pointer to the parsed string
*/
-rsRetVal parsDelimCStr(rsParsObj *pThis, cstr_t **ppCStr, char cDelim, int bTrimLeading, int bTrimTrailing);
+rsRetVal parsDelimCStr(rsParsObj *pThis, cstr_t **ppCStr, char cDelim, int bTrimLeading, int bTrimTrailing, int bConvLower);
rsRetVal parsSkipAfterChar(rsParsObj *pThis, char c);
rsRetVal parsQuotedCStr(rsParsObj *pThis, cstr_t **ppCStr);
diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c
index 162cab9..75e54f0 100644
--- a/plugins/imfile/imfile.c
+++ b/plugins/imfile/imfile.c
@@ -95,7 +95,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine)
MsgSetUxTradMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine));
MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine));
MsgSetMSG(pMsg, (char*)rsCStrGetSzStr(cstrLine));
- MsgSetHOSTNAME(pMsg, LocalHostName);
+ MsgSetHOSTNAME(pMsg, (char*)LocalHostName);
MsgSetTAG(pMsg, (char*)pInfo->pszTag);
pMsg->iFacility = LOG_FAC(pInfo->iFacility);
pMsg->iSeverity = LOG_PRI(pInfo->iSeverity);
@@ -379,6 +379,9 @@ ENDafterRun
*/
BEGINmodExit
CODESTARTmodExit
+ /* release objects we used */
+ objRelease(datetime, CORE_COMPONENT);
+ objRelease(errmsg, CORE_COMPONENT);
ENDmodExit
diff --git a/plugins/imklog/Makefile.am b/plugins/imklog/Makefile.am
index 11e0096..246b330 100644
--- a/plugins/imklog/Makefile.am
+++ b/plugins/imklog/Makefile.am
@@ -1,6 +1,16 @@
pkglib_LTLIBRARIES = imklog.la
-imklog_la_SOURCES = imklog.c imklog.h module.h ksym.c ksyms.h ksym_mod.c
+imklog_la_SOURCES = imklog.c imklog.h
+
+# select klog "driver"
+if ENABLE_IMKLOG_BSD
+imklog_la_SOURCES += bsd.c
+endif
+
+if ENABLE_IMKLOG_LINUX
+imklog_la_SOURCES += linux.c module.h ksym.c ksyms.h ksym_mod.c
+endif
+
imklog_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags)
imklog_la_LDFLAGS = -module -avoid-version
imklog_la_LIBADD =
diff --git a/plugins/imklog/Makefile.in b/plugins/imklog/Makefile.in
index 3e7802e..08134db 100644
--- a/plugins/imklog/Makefile.in
+++ b/plugins/imklog/Makefile.in
@@ -32,6 +32,10 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
+
+# select klog "driver"
+@ENABLE_IMKLOG_BSD_TRUE@am__append_1 = bsd.c
+@ENABLE_IMKLOG_LINUX_TRUE@am__append_2 = linux.c module.h ksym.c ksyms.h ksym_mod.c
subdir = plugins/imklog
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -51,8 +55,14 @@ am__installdirs = "$(DESTDIR)$(pkglibdir)"
pkglibLTLIBRARIES_INSTALL = $(INSTALL)
LTLIBRARIES = $(pkglib_LTLIBRARIES)
imklog_la_DEPENDENCIES =
-am_imklog_la_OBJECTS = imklog_la-imklog.lo imklog_la-ksym.lo \
- imklog_la-ksym_mod.lo
+am__imklog_la_SOURCES_DIST = imklog.c imklog.h bsd.c linux.c module.h \
+ ksym.c ksyms.h ksym_mod.c
+@ENABLE_IMKLOG_BSD_TRUE@am__objects_1 = imklog_la-bsd.lo
+@ENABLE_IMKLOG_LINUX_TRUE@am__objects_2 = imklog_la-linux.lo \
+@ENABLE_IMKLOG_LINUX_TRUE@ imklog_la-ksym.lo \
+@ENABLE_IMKLOG_LINUX_TRUE@ imklog_la-ksym_mod.lo
+am_imklog_la_OBJECTS = imklog_la-imklog.lo $(am__objects_1) \
+ $(am__objects_2)
imklog_la_OBJECTS = $(am_imklog_la_OBJECTS)
imklog_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@@ -70,7 +80,7 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(imklog_la_SOURCES)
-DIST_SOURCES = $(imklog_la_SOURCES)
+DIST_SOURCES = $(am__imklog_la_SOURCES_DIST)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -202,7 +212,7 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
zlib_libs = @zlib_libs@
pkglib_LTLIBRARIES = imklog.la
-imklog_la_SOURCES = imklog.c imklog.h module.h ksym.c ksyms.h ksym_mod.c
+imklog_la_SOURCES = imklog.c imklog.h $(am__append_1) $(am__append_2)
imklog_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags)
imklog_la_LDFLAGS = -module -avoid-version
imklog_la_LIBADD =
@@ -275,9 +285,11 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imklog_la-bsd.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imklog_la-imklog.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imklog_la-ksym.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imklog_la-ksym_mod.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imklog_la-linux.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -307,6 +319,20 @@ imklog_la-imklog.lo: imklog.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imklog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imklog_la-imklog.lo `test -f 'imklog.c' || echo '$(srcdir)/'`imklog.c
+imklog_la-bsd.lo: bsd.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imklog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imklog_la-bsd.lo -MD -MP -MF $(DEPDIR)/imklog_la-bsd.Tpo -c -o imklog_la-bsd.lo `test -f 'bsd.c' || echo '$(srcdir)/'`bsd.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/imklog_la-bsd.Tpo $(DEPDIR)/imklog_la-bsd.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bsd.c' object='imklog_la-bsd.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imklog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imklog_la-bsd.lo `test -f 'bsd.c' || echo '$(srcdir)/'`bsd.c
+
+imklog_la-linux.lo: linux.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imklog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imklog_la-linux.lo -MD -MP -MF $(DEPDIR)/imklog_la-linux.Tpo -c -o imklog_la-linux.lo `test -f 'linux.c' || echo '$(srcdir)/'`linux.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/imklog_la-linux.Tpo $(DEPDIR)/imklog_la-linux.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='linux.c' object='imklog_la-linux.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imklog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imklog_la-linux.lo `test -f 'linux.c' || echo '$(srcdir)/'`linux.c
+
imklog_la-ksym.lo: ksym.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imklog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imklog_la-ksym.lo -MD -MP -MF $(DEPDIR)/imklog_la-ksym.Tpo -c -o imklog_la-ksym.lo `test -f 'ksym.c' || echo '$(srcdir)/'`ksym.c
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/imklog_la-ksym.Tpo $(DEPDIR)/imklog_la-ksym.Plo
diff --git a/plugins/imklog/bsd.c b/plugins/imklog/bsd.c
new file mode 100644
index 0000000..39b644c
--- /dev/null
+++ b/plugins/imklog/bsd.c
@@ -0,0 +1,181 @@
+/* klog for BSD, based on the FreeBSD syslogd implementation.
+ *
+ * This contains OS-specific functionality to read the BSD
+ * kernel log. For a general overview, see head comment in
+ * imklog.c.
+ *
+ * Copyright (C) 2008 by Rainer Gerhards for the modifications of
+ * the original FreeBSD sources.
+ *
+ * I would like to express my gratitude to those folks which
+ * layed an important foundation for rsyslog to build on.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Rsyslog is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ *
+ * This file is based on earlier work included in the FreeBSD sources. We
+ * integrated it into the rsyslog project. The copyright below applies, and
+ * I also reproduce the original license under which we aquired the code:
+ *
+ * Copyright (c) 1983, 1988, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * If you would like to use the code under the BSD license, you should
+ * aquire your own copy of BSD's syslogd, from which we have taken it. The
+ * code in this file is modified and may only be used under the terms of
+ * the GPLv3+ as specified above.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+#include "rsyslog.h"
+#include "imklog.h"
+
+/* globals */
+static int fklog = -1; /* /dev/klog */
+
+#ifndef _PATH_KLOG
+# define _PATH_KLOG "/dev/klog"
+#endif
+
+/* open the kernel log - will be called inside the willRun() imklog
+ * entry point. -- rgerhards, 2008-04-09
+ */
+rsRetVal
+klogWillRun(void)
+{
+ DEFiRet;
+
+ fklog = open(_PATH_KLOG, O_RDONLY, 0);
+ if (fklog < 0) {
+ dbgprintf("can't open %s (%d)\n", _PATH_KLOG, errno);
+ iRet = RS_RET_ERR; // TODO: better error code
+ }
+
+ RETiRet;
+}
+
+
+/* Read /dev/klog while data are available, split into lines.
+ * Contrary to standard BSD syslogd, we do a blocking read. We can
+ * afford this as imklog is running on its own threads. So if we have
+ * a single file, it really doesn't matter if we wait inside a 1-file
+ * select or the read() directly.
+ */
+static void
+readklog(void)
+{
+ char *p, *q, line[MAXLINE + 1];
+ int len, i;
+
+ len = 0;
+ for (;;) {
+ dbgprintf("----------imklog waiting for kernel log line\n");
+ i = read(fklog, line + len, MAXLINE - 1 - len);
+ if (i > 0) {
+ line[i + len] = '\0';
+ } else {
+ if (i < 0 && errno != EINTR && errno != EAGAIN) {
+ imklogLogIntMsg(LOG_ERR,
+ "imklog error %d reading kernel log - shutting down imklog",
+ errno);
+ fklog = -1;
+ }
+ break;
+ }
+
+ for (p = line; (q = strchr(p, '\n')) != NULL; p = q + 1) {
+ *q = '\0';
+ Syslog(LOG_INFO, (uchar*) p);
+ }
+ len = strlen(p);
+ if (len >= MAXLINE - 1) {
+ Syslog(LOG_INFO, (uchar*)p);
+ len = 0;
+ }
+ if (len > 0)
+ memmove(line, p, len + 1);
+ }
+ if (len > 0)
+ Syslog(LOG_INFO, (uchar*)line);
+}
+
+
+/* to be called in the module's AfterRun entry point
+ * rgerhards, 2008-04-09
+ */
+rsRetVal klogAfterRun(void)
+{
+ DEFiRet;
+ if(fklog != -1)
+ close(fklog);
+ RETiRet;
+}
+
+
+
+/* to be called in the module's WillRun entry point, this is the main
+ * "message pull" mechanism.
+ * rgerhards, 2008-04-09
+ */
+rsRetVal klogLogKMsg(void)
+{
+ DEFiRet;
+ readklog();
+ RETiRet;
+}
+
+
+/* provide the (system-specific) default facility for internal messages
+ * rgerhards, 2008-04-14
+ */
+int
+klogFacilIntMsg(void)
+{
+ return LOG_SYSLOG;
+}
diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c
index bfea8c6..f7aee5b 100644
--- a/plugins/imklog/imklog.c
+++ b/plugins/imklog/imklog.c
@@ -1,14 +1,24 @@
-/* The kernel log input module for Linux. This file heavily
- * borrows from the klogd daemon provided by the sysklogd project.
- * Many thanks for this piece of software.
+/* The kernel log module.
+ *
+ * This is an abstracted module. As Linux and BSD kernel log is conceptually the
+ * same, we do not do different input plugins for them but use
+ * imklog in both cases, just with different "backend drivers" for
+ * the different platforms. This also enables a rsyslog.conf to
+ * be used on multiple platforms without the need to take care of
+ * what the kernel log is coming from.
+ *
+ * See platform-specific files (e.g. linux.c, bsd.c) in the plugin's
+ * working directory. For other systems with similar kernel logging
+ * functionality, no new input plugin shall be written but rather a
+ * driver be developed for imklog. Please note that imklog itself is
+ * mostly concerned with handling the interface. Any real action happens
+ * in the drivers, as things may be pretty different on different
+ * platforms.
*
* Please note that this file replaces the klogd daemon that was
* also present in pre-v3 versions of rsyslog.
*
- * I have begun to convert this to an input module on 2007-12-17.
- * IMPORTANT: more than a single instance is currently not supported. This
- * needs to be revisited once the config file and input module interface
- * supports multiple instances!
+ * Copyright (C) 2008 by Rainer Gerhards and Adiscon GmbH
*
* This file is part of rsyslog.
*
@@ -29,559 +39,158 @@
*/
#include "config.h"
#include "rsyslog.h"
-#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
-#include <signal.h>
#include <string.h>
-#include <pthread.h>
+#include <stdarg.h>
+#include <ctype.h>
+
#include "syslogd.h"
#include "cfsysline.h"
-#include "template.h"
+#include "obj.h"
#include "msg.h"
#include "module-template.h"
+#include "datetime.h"
#include "imklog.h"
MODULE_TYPE_INPUT
/* Module static data */
DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(datetime)
/* configuration settings TODO: move to instance data? */
int dbgPrintSymbols = 0; /* this one is extern so the helpers can access it! */
-static int symbols_twice = 0;
-static int use_syscall = 0;
-static int symbol_lookup = 1;
+int symbols_twice = 0;
+int use_syscall = 0;
+int symbol_lookup = 0; /* on recent kernels > 2.6, the kernel does this */
+int bPermitNonKernel = 0; /* permit logging of messages not having LOG_KERN facility */
+int iFacilIntMsg; /* the facility to use for internal messages (set by driver) */
/* TODO: configuration for the following directives must be implemented. It
* was not done yet because we either do not yet have a config handler for
* that type or I thought it was acceptable to push it to a later stage when
* I gained more handson experience with the input module interface (and the
* changes resulting from that). -- rgerhards, 2007-12-20
*/
-static char *symfile = NULL;
-static int console_log_level = -1;
-
-
-/* Includes. */
-#include <unistd.h>
-#include <errno.h>
-#include <sys/fcntl.h>
-#include <sys/stat.h>
-
-#if HAVE_TIME_H
-# include <time.h>
-#endif
-
-#include <stdarg.h>
-#include <paths.h>
-#include "ksyms.h"
-
-#define __LIBRARY__
-#include <unistd.h>
-
-
-#if !defined(__GLIBC__)
-# define __NR_ksyslog __NR_syslog
-_syscall3(int,ksyslog,int, type, char *, buf, int, len);
-#else
-#include <sys/klog.h>
-#define ksyslog klogctl
-#endif
-
-
-
-#ifndef _PATH_KLOG
-#define _PATH_KLOG "/proc/kmsg"
-#endif
-
-#define LOG_BUFFER_SIZE 4096
-#define LOG_LINE_LENGTH 1000
-
-static int kmsg;
-static char log_buffer[LOG_BUFFER_SIZE];
-
-static enum LOGSRC {none, proc, kernel} logsrc;
-
+char *symfile = NULL;
+int console_log_level = -1;
-/* Function prototypes. */
-extern int ksyslog(int type, char *buf, int len);
-
-
-/* Write a message to the message queue.
- * returns -1 if it fails, something else otherwise
+/* enqueue the the kernel message into the message queue.
+ * The provided msg string is not freed - thus must be done
+ * by the caller.
+ * rgerhards, 2008-04-12
*/
-static rsRetVal writeSyslogV(int iPRI, const char *szFmt, va_list va)
+static rsRetVal
+enqMsg(uchar *msg, uchar* pszTag, int iFacility, int iSeverity)
{
DEFiRet;
- int iChars;
- int iLen;
- time_t tNow;
- char msgBuf[2048]; /* we use the same size as sysklogd to remain compatible */
-
- assert(szFmt != NULL);
-
- /* build the message */
- time(&tNow);
- /* we can use sprintf safely below, because we know the size of the constants.
- * By doing so, we save some cpu cycles and code complexity (for unnecessary
- * error checking).
- */
- iLen = sprintf(msgBuf, "<%d>%.15s kernel: ", iPRI, ctime(&tNow) + 4);
-
- iChars = vsnprintf(msgBuf + iLen, sizeof(msgBuf) / sizeof(char) - iLen, szFmt, va);
-
- /* here we must create our message object and supply it to the message queue
- */
- CHKiRet(parseAndSubmitMessage(LocalHostName, msgBuf, strlen(msgBuf), MSG_DONT_PARSE_HOSTNAME, NOFLAG, eFLOWCTL_LIGHT_DELAY));
+ msg_t *pMsg;
+
+ assert(msg != NULL);
+ assert(pszTag != NULL);
+
+ CHKiRet(msgConstruct(&pMsg));
+ MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY);
+ MsgSetUxTradMsg(pMsg, (char*)msg);
+ MsgSetRawMsg(pMsg, (char*)msg);
+ MsgSetMSG(pMsg, (char*)msg);
+ MsgSetHOSTNAME(pMsg, (char*)LocalHostName);
+ MsgSetTAG(pMsg, (char*)pszTag);
+ pMsg->iFacility = LOG_FAC(iFacility);
+ pMsg->iSeverity = LOG_PRI(iSeverity);
+ pMsg->bParseHOSTNAME = 0;
+ datetime.getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */
+ CHKiRet(submitMsg(pMsg));
finalize_it:
RETiRet;
}
-/* And now the same with variable arguments */
-static int writeSyslog(int iPRI, const char *szFmt, ...)
-{
- int iRet;
- va_list va;
-
- assert(szFmt != NULL);
- va_start(va, szFmt);
- iRet = writeSyslogV(iPRI, szFmt, va);
- va_end(va);
-
- return(iRet);
-}
-
-rsRetVal Syslog(int priority, char *fmt, ...) __attribute__((format(printf,2, 3)));
-rsRetVal Syslog(int priority, char *fmt, ...)
+/* parse the PRI from a kernel message. At least BSD seems to have
+ * non-kernel messages inside the kernel log...
+ * Expected format: "<pri>". piPri is only valid if the function
+ * successfully returns. If there was a proper pri ppSz is advanced to the
+ * position right after ">".
+ * rgerhards, 2008-04-14
+ */
+static rsRetVal
+parsePRI(uchar **ppSz, int *piPri)
{
DEFiRet;
- va_list ap;
- char *argl;
-
- /* Output using syslog. */
- if (!strcmp(fmt, "%s")) {
- va_start(ap, fmt);
- argl = va_arg(ap, char *);
- if (argl[0] == '<' && argl[1] && argl[2] == '>') {
- switch ( argl[1] )
- {
- case '0':
- priority = LOG_EMERG;
- break;
- case '1':
- priority = LOG_ALERT;
- break;
- case '2':
- priority = LOG_CRIT;
- break;
- case '3':
- priority = LOG_ERR;
- break;
- case '4':
- priority = LOG_WARNING;
- break;
- case '5':
- priority = LOG_NOTICE;
- break;
- case '6':
- priority = LOG_INFO;
- break;
- case '7':
- default:
- priority = LOG_DEBUG;
- }
- argl += 3;
- }
- iRet = writeSyslog(priority, fmt, argl);
- va_end(ap);
- } else {
- va_start(ap, fmt);
- iRet = writeSyslogV(priority, fmt, ap);
- va_end(ap);
- }
-
- RETiRet;
-}
-
-
-static void CloseLogSrc(void)
-{
- /* Turn on logging of messages to console, but only if we had the -c
- * option -- rgerhards, 2007-08-01
- */
- if (console_log_level != -1)
- ksyslog(7, NULL, 0);
-
- /* Shutdown the log sources. */
- switch ( logsrc )
- {
- case kernel:
- ksyslog(0, 0, 0);
- Syslog(LOG_INFO, "Kernel logging (ksyslog) stopped.");
- break;
- case proc:
- close(kmsg);
- Syslog(LOG_INFO, "Kernel logging (proc) stopped.");
- break;
- case none:
- break;
- }
+ int i;
+ uchar *pSz;
- return;
-}
+ assert(ppSz != NULL);
+ pSz = *ppSz;
+ assert(pSz != NULL);
+ assert(piPri != NULL);
+ if(*pSz != '<' || !isdigit(*(pSz+1)))
+ ABORT_FINALIZE(RS_RET_INVALID_PRI);
-static enum LOGSRC GetKernelLogSrc(void)
-{
- auto struct stat sb;
-
- /* Set level of kernel console messaging.. */
- if ( (console_log_level != -1) &&
- (ksyslog(8, NULL, console_log_level) < 0) &&
- (errno == EINVAL) )
- {
- /*
- * An invalid arguement error probably indicates that
- * a pre-0.14 kernel is being run. At this point we
- * issue an error message and simply shut-off console
- * logging completely.
- */
- Syslog(LOG_WARNING, "Cannot set console log level - disabling "
- "console output.");
+ ++pSz;
+ i = 0;
+ while(isdigit(*pSz)) {
+ i = i * 10 + *pSz++ - '0';
}
- /*
- * First do a stat to determine whether or not the proc based
- * file system is available to get kernel messages from.
- */
- if ( use_syscall ||
- ((stat(_PATH_KLOG, &sb) < 0) && (errno == ENOENT)) )
- {
- /* Initialize kernel logging. */
- ksyslog(1, NULL, 0);
- Syslog(LOG_INFO, "imklogd %s, log source = ksyslog "
- "started.", VERSION);
- return(kernel);
- }
+ if(*pSz != '>')
+ ABORT_FINALIZE(RS_RET_INVALID_PRI);
- if ( (kmsg = open(_PATH_KLOG, O_RDONLY)) < 0 )
- {
- char sz[512];
- snprintf(sz, sizeof(sz), "imklog: Cannot open proc file system, %d - %s.\n", errno, strerror(errno));
- logmsgInternal(LOG_SYSLOG|LOG_ERR, sz, ADDDATE);
- ksyslog(7, NULL, 0); /* TODO: check this, implement more */
- return(none);
- }
+ /* OK, we have a valid PRI */
+ *piPri = i;
+ *ppSz = pSz + 1; /* update msg ptr to position after PRI */
- Syslog(LOG_INFO, "imklog %s, log source = %s started.", \
- VERSION, _PATH_KLOG);
- return(proc);
+finalize_it:
+ RETiRet;
}
-/* Copy characters from ptr to line until a char in the delim
- * string is encountered or until min( space, len ) chars have
- * been copied.
- *
- * Returns the actual number of chars copied.
+/* log an imklog-internal message
+ * rgerhards, 2008-04-14
*/
-static int copyin( char *line, int space,
- const char *ptr, int len,
- const char *delim )
+rsRetVal imklogLogIntMsg(int priority, char *fmt, ...)
{
- auto int i;
- auto int count;
-
- count = len < space ? len : space;
+ DEFiRet;
+ va_list ap;
+ uchar msgBuf[2048]; /* we use the same size as sysklogd to remain compatible */
+ uchar *pLogMsg;
- for(i=0; i<count && !strchr(delim, *ptr); i++ ) {
- *line++ = *ptr++;
- }
+ va_start(ap, fmt);
+ vsnprintf((char*)msgBuf, sizeof(msgBuf) / sizeof(char), fmt, ap);
+ pLogMsg = msgBuf;
+ va_end(ap);
- return(i);
-}
+ iRet = enqMsg((uchar*)pLogMsg, (uchar*) ((iFacilIntMsg == LOG_KERN) ? "kernel:" : "imklog:"),
+ iFacilIntMsg, LOG_PRI(priority));
-/*
- * Messages are separated by "\n". Messages longer than
- * LOG_LINE_LENGTH are broken up.
- *
- * Kernel symbols show up in the input buffer as : "[<aaaaaa>]",
- * where "aaaaaa" is the address. These are replaced with
- * "[symbolname+offset/size]" in the output line - symbolname,
- * offset, and size come from the kernel symbol table.
- *
- * If a kernel symbol happens to fall at the end of a message close
- * in length to LOG_LINE_LENGTH, the symbol will not be expanded.
- * (This should never happen, since the kernel should never generate
- * messages that long.
- *
- * To preserve the original addresses, lines containing kernel symbols
- * are output twice. Once with the symbols converted and again with the
- * original text. Just in case somebody wants to run their own Oops
- * analysis on the syslog, e.g. ksymoops.
- */
-static void LogLine(char *ptr, int len)
-{
- enum parse_state_enum {
- PARSING_TEXT,
- PARSING_SYMSTART, /* at < */
- PARSING_SYMBOL,
- PARSING_SYMEND /* at ] */
- };
-
- static char line_buff[LOG_LINE_LENGTH];
-
- static char *line =line_buff;
- static enum parse_state_enum parse_state = PARSING_TEXT;
- static int space = sizeof(line_buff)-1;
-
- static char *sym_start; /* points at the '<' of a symbol */
-
- auto int delta = 0; /* number of chars copied */
- auto int symbols_expanded = 0; /* 1 if symbols were expanded */
- auto int skip_symbol_lookup = 0; /* skip symbol lookup on this pass */
- auto char *save_ptr = ptr; /* save start of input line */
- auto int save_len = len; /* save length at start of input line */
-
- while( len > 0 )
- {
- if( space == 0 ) /* line buffer is full */
- {
- /*
- ** Line too long. Start a new line.
- */
- *line = 0; /* force null terminator */
-
- dbgprintf("Line buffer full:\n");
- dbgprintf("\tLine: %s\n", line);
-
- Syslog( LOG_INFO, "%s", line_buff );
- line = line_buff;
- space = sizeof(line_buff)-1;
- parse_state = PARSING_TEXT;
- symbols_expanded = 0;
- skip_symbol_lookup = 0;
- save_ptr = ptr;
- save_len = len;
- }
-
- switch( parse_state )
- {
- case PARSING_TEXT:
- delta = copyin( line, space, ptr, len, "\n[" );
- line += delta;
- ptr += delta;
- space -= delta;
- len -= delta;
-
- if( space == 0 || len == 0 )
- {
- break; /* full line_buff or end of input buffer */
- }
-
- if( *ptr == '\0' ) /* zero byte */
- {
- ptr++; /* skip zero byte */
- space -= 1;
- len -= 1;
-
- break;
- }
-
- if( *ptr == '\n' ) /* newline */
- {
- ptr++; /* skip newline */
- space -= 1;
- len -= 1;
-
- *line = 0; /* force null terminator */
- Syslog( LOG_INFO, "%s", line_buff );
- line = line_buff;
- space = sizeof(line_buff)-1;
- if (symbols_twice) {
- if (symbols_expanded) {
- /* reprint this line without symbol lookup */
- symbols_expanded = 0;
- skip_symbol_lookup = 1;
- ptr = save_ptr;
- len = save_len;
- }
- else
- {
- skip_symbol_lookup = 0;
- save_ptr = ptr;
- save_len = len;
- }
- }
- break;
- }
- if( *ptr == '[' ) /* possible kernel symbol */
- {
- *line++ = *ptr++;
- space -= 1;
- len -= 1;
- if (!skip_symbol_lookup)
- parse_state = PARSING_SYMSTART; /* at < */
- break;
- }
- /* Now that line_buff is no longer fed to *printf as format
- * string, '%'s are no longer "dangerous".
- */
- break;
-
- case PARSING_SYMSTART:
- if( *ptr != '<' )
- {
- parse_state = PARSING_TEXT; /* not a symbol */
- break;
- }
-
- /*
- ** Save this character for now. If this turns out to
- ** be a valid symbol, this char will be replaced later.
- ** If not, we'll just leave it there.
- */
-
- sym_start = line; /* this will point at the '<' */
-
- *line++ = *ptr++;
- space -= 1;
- len -= 1;
- parse_state = PARSING_SYMBOL; /* symbol... */
- break;
-
- case PARSING_SYMBOL:
- delta = copyin( line, space, ptr, len, ">\n[" );
- line += delta;
- ptr += delta;
- space -= delta;
- len -= delta;
- if( space == 0 || len == 0 )
- {
- break; /* full line_buff or end of input buffer */
- }
- if( *ptr != '>' )
- {
- parse_state = PARSING_TEXT;
- break;
- }
-
- *line++ = *ptr++; /* copy the '>' */
- space -= 1;
- len -= 1;
-
- parse_state = PARSING_SYMEND;
-
- break;
-
- case PARSING_SYMEND:
- if( *ptr != ']' )
- {
- parse_state = PARSING_TEXT; /* not a symbol */
- break;
- }
-
- /*
- ** It's really a symbol! Replace address with the
- ** symbol text.
- */
- {
- auto int sym_space;
-
- unsigned long value;
- auto struct symbol sym;
- auto char *symbol;
-
- *(line-1) = 0; /* null terminate the address string */
- value = strtoul(sym_start+1, (char **) 0, 16);
- *(line-1) = '>'; /* put back delim */
-
- if ( !symbol_lookup || (symbol = LookupSymbol(value, &sym)) == (char *)0 )
- {
- parse_state = PARSING_TEXT;
- break;
- }
-
- /*
- ** verify there is room in the line buffer
- */
- sym_space = space + ( line - sym_start );
- if( (unsigned) sym_space < strlen(symbol) + 30 ) /*(30 should be overkill)*/
- {
- parse_state = PARSING_TEXT; /* not enough space */
- break;
- }
-
- delta = sprintf( sym_start, "%s+%d/%d]",
- symbol, sym.offset, sym.size );
-
- space = sym_space + delta;
- line = sym_start + delta;
- symbols_expanded = 1;
- }
- ptr++;
- len--;
- parse_state = PARSING_TEXT;
- break;
-
- default: /* Can't get here! */
- parse_state = PARSING_TEXT;
-
- }
- }
-
- return;
+ RETiRet;
}
-static void LogKernelLine(void)
+/* log a kernel message
+ * rgerhards, 2008-04-14
+ */
+rsRetVal Syslog(int priority, uchar *pMsg)
{
- auto int rdcnt;
+ DEFiRet;
+ rsRetVal localRet;
- /*
- * Zero-fill the log buffer. This should cure a multitude of
- * problems with klogd logging the tail end of the message buffer
- * which will contain old messages. Then read the kernel log
- * messages into this fresh buffer.
- */
- memset(log_buffer, '\0', sizeof(log_buffer));
- if ( (rdcnt = ksyslog(2, log_buffer, sizeof(log_buffer)-1)) < 0 )
- {
- char sz[512];
- if(errno == EINTR)
- return;
- snprintf(sz, sizeof(sz), "imklog: Error return from sys_sycall: %d - %s\n", errno, strerror(errno));
- logmsgInternal(LOG_SYSLOG|LOG_ERR, sz, ADDDATE);
- }
- else
- LogLine(log_buffer, rdcnt);
- return;
-}
+ /* Output using syslog */
+ localRet = parsePRI(&pMsg, &priority);
+ if(localRet != RS_RET_INVALID_PRI && localRet != RS_RET_OK)
+ FINALIZE;
+ /* if we don't get the pri, we use whatever we were supplied */
+ /* ignore non-kernel messages if not permitted */
+ if(bPermitNonKernel == 0 && LOG_FAC(priority) != LOG_KERN)
+ FINALIZE; /* silently ignore */
-static void LogProcLine(void)
-{
- auto int rdcnt;
+ iRet = enqMsg((uchar*)pMsg, (uchar*) "kernel:", LOG_FAC(priority), LOG_PRI(priority));
- /*
- * Zero-fill the log buffer. This should cure a multitude of
- * problems with klogd logging the tail end of the message buffer
- * which will contain old messages. Then read the kernel messages
- * from the message pseudo-file into this fresh buffer.
- */
- memset(log_buffer, '\0', sizeof(log_buffer));
- if ( (rdcnt = read(kmsg, log_buffer, sizeof(log_buffer)-1)) < 0 )
- {
- if ( errno == EINTR )
- return;
- Syslog(LOG_ERR, "Cannot read proc file system: %d - %s.", errno, strerror(errno));
- }
- else
- LogLine(log_buffer, rdcnt);
-
- return;
+finalize_it:
+ RETiRet;
}
@@ -592,64 +201,32 @@ CODESTARTrunInput
* right into the sleep below.
*/
while(!pThrd->bShallStop) {
- /* we do not need to handle the RS_RET_TERMINATE_NOW case any
- * special because we just need to terminate. This may be different
- * if a cleanup is needed. But for now, we can just use CHKiRet().
- * rgerhards, 2007-12-17
+ /* klogLogKMsg() waits for the next kernel message, obtains it
+ * and then submits it to the rsyslog main queue.
+ * rgerhards, 2008-04-09
*/
- switch ( logsrc )
- {
- case kernel:
- LogKernelLine();
- break;
- case proc:
- LogProcLine();
- break;
- case none:
- /* TODO: We need to handle this case here somewhat more intelligent
- * This is now at least partly done - code should never reach this point
- * as willRun() already checked for the "none" status -- rgerhards, 2007-12-17
- */
- pause();
- break;
- }
+ CHKiRet(klogLogKMsg());
}
- RETiRet;
+finalize_it:
ENDrunInput
BEGINwillRun
- /* Initialize this module. If that fails, we tell the engine we don't like to run */
- /* Determine where kernel logging information is to come from. */
- logsrc = GetKernelLogSrc();
- if(logsrc == none) {
- iRet = RS_RET_NO_KERNEL_LOGSRC;
- } else {
- if (symbol_lookup) {
- symbol_lookup = (InitKsyms(symfile) == 1);
- symbol_lookup |= InitMsyms();
- if (symbol_lookup == 0) {
- Syslog(LOG_WARNING, "cannot find any symbols, turning off symbol lookups\n");
- }
- }
- }
CODESTARTwillRun
+ iRet = klogWillRun();
ENDwillRun
BEGINafterRun
CODESTARTafterRun
- /* cleanup here */
- if(logsrc != none)
- CloseLogSrc();
-
- DeinitKsyms();
- DeinitMsyms();
+ iRet = klogAfterRun();
ENDafterRun
BEGINmodExit
CODESTARTmodExit
+ /* release objects we used */
+ objRelease(datetime, CORE_COMPONENT);
ENDmodExit
@@ -664,7 +241,9 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
symbols_twice = 0;
use_syscall = 0;
symfile = NULL;
- symbol_lookup = 1;
+ symbol_lookup = 0;
+ bPermitNonKernel = 0;
+ iFacilIntMsg = klogFacilIntMsg();
return RS_RET_OK;
}
@@ -672,17 +251,17 @@ BEGINmodInit()
CODESTARTmodInit
*ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+
+ iFacilIntMsg = klogFacilIntMsg();
+
CHKiRet(omsdRegCFSLineHdlr((uchar *)"debugprintkernelsymbols", 0, eCmdHdlrBinary, NULL, &dbgPrintSymbols, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbollookup", 0, eCmdHdlrBinary, NULL, &symbol_lookup, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbolstwice", 0, eCmdHdlrBinary, NULL, &symbols_twice, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogusesyscallinterface", 0, eCmdHdlrBinary, NULL, &use_syscall, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogpermitnonkernelfacility", 0, eCmdHdlrBinary, NULL, &bPermitNonKernel, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"kloginternalmsgfacility", 0, eCmdHdlrFacility, NULL, &iFacilIntMsg, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
ENDmodInit
-/*
- * Local variables:
- * c-indent-level: 8
- * c-basic-offset: 8
- * tab-width: 8
- * End:
- * vi:set ai:
+/* vim:set ai:
*/
diff --git a/plugins/imklog/imklog.h b/plugins/imklog/imklog.h
index 71525a7..a37ecc9 100644
--- a/plugins/imklog/imklog.h
+++ b/plugins/imklog/imklog.h
@@ -2,8 +2,10 @@
* These are the definitions for the klog message generation module.
*
* File begun on 2007-12-17 by RGerhards
+ * Major change: 2008-04-09: switched to a driver interface for
+ * several platforms
*
- * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2007-2008 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of rsyslog.
*
@@ -28,9 +30,33 @@
#include "rsyslog.h"
#include "syslogd.h"
-/* global variables */
+/* interface to "drivers"
+ * the platform specific drivers must implement these entry points. Only one
+ * driver may be active at any given time, thus we simply rely on the linker
+ * to resolve the addresses.
+ * rgerhards, 2008-04-09
+ */
+rsRetVal klogLogKMsg(void);
+rsRetVal klogWillRun(void);
+rsRetVal klogAfterRun(void);
+int klogFacilIntMsg(void);
+
+/* the following data members may be accessed by the "drivers"
+ * I admit this is not the cleanest way to doing things, but I honestly
+ * believe it is appropriate for the job that needs to be done.
+ * rgerhards, 2008-04-09
+ */
+extern int symbols_twice;
+extern int use_syscall;
+extern int symbol_lookup;
+extern char *symfile;
+extern int console_log_level;
extern int dbgPrintSymbols;
+/* the functions below may be called by the drivers */
+rsRetVal imklogLogIntMsg(int priority, char *fmt, ...) __attribute__((format(printf,2, 3)));
+rsRetVal Syslog(int priority, uchar *msg);
+
/* prototypes */
extern int InitKsyms(char *);
extern void DeinitKsyms(void);
@@ -38,8 +64,6 @@ extern int InitMsyms(void);
extern void DeinitMsyms(void);
extern char * ExpandKadds(char *, char *);
extern void SetParanoiaLevel(int);
-extern void vsyslog(int pri, const char *fmt, va_list ap);
-rsRetVal Syslog(int priority, char *fmt, ...) __attribute__((format(printf,2, 3)));
#endif /* #ifndef IMKLOG_H_INCLUDED */
/* vi:set ai:
diff --git a/plugins/imklog/ksym.c b/plugins/imklog/ksym.c
index b7d5903..f636a7b 100644
--- a/plugins/imklog/ksym.c
+++ b/plugins/imklog/ksym.c
@@ -138,7 +138,7 @@ static char *system_maps[] =
/* Function prototypes. */
-static char * FindSymbolFile(void);
+static char *FindSymbolFile(void);
static int AddSymbol(unsigned long, char*);
static void FreeSymbols(void);
static int CheckVersion(char *);
@@ -173,38 +173,36 @@ extern int InitKsyms(char *mapfile)
auto FILE *sym_file;
+ BEGINfunc
/* Check and make sure that we are starting with a clean slate. */
if ( num_syms > 0 )
FreeSymbols();
- /*
- * Search for and open the file containing the kernel symbols.
- */
- if ( mapfile != (char *) 0 ) {
- if ( (sym_file = fopen(mapfile, "r")) == (FILE *) 0 )
+ /* Search for and open the file containing the kernel symbols. */
+ if ( mapfile != NULL ) {
+ if ( (sym_file = fopen(mapfile, "r")) == NULL )
{
- Syslog(LOG_WARNING, "Cannot open map file: %s.", mapfile);
+ imklogLogIntMsg(LOG_WARNING, "Cannot open map file: %s.", mapfile);
return(0);
}
} else {
- if ( (mapfile = FindSymbolFile()) == (char *) 0 ) {
- Syslog(LOG_WARNING, "Cannot find map file.");
+ if ( (mapfile = FindSymbolFile()) == NULL ) {
+ imklogLogIntMsg(LOG_WARNING, "Cannot find map file.");
dbgprintf("Cannot find map file.\n");
return(0);
}
- if ( (sym_file = fopen(mapfile, "r")) == (FILE *) 0 ) {
- Syslog(LOG_WARNING, "Cannot open map file.");
+ if ( (sym_file = fopen(mapfile, "r")) == NULL ) {
+ imklogLogIntMsg(LOG_WARNING, "Cannot open map file.");
dbgprintf("Cannot open map file.\n");
return(0);
}
}
- /*
- * Read the kernel symbol table file and add entries for each
+ /* Read the kernel symbol table file and add entries for each
* line. I suspect that the use of fscanf is not really in vogue
* but it was quick and dirty and IMHO suitable for fixed format
* data such as this. If anybody doesn't agree with this please
@@ -213,7 +211,7 @@ extern int InitKsyms(char *mapfile)
*/
while ( !feof(sym_file) ) {
if ( fscanf(sym_file, "%lx %c %s\n", &address, &type, sym) != 3 ) {
- Syslog(LOG_ERR, "Error in symbol table input (#1).");
+ imklogLogIntMsg(LOG_ERR, "Error in symbol table input (#1).");
fclose(sym_file);
return(0);
}
@@ -221,7 +219,7 @@ extern int InitKsyms(char *mapfile)
dbgprintf("Address: %lx, Type: %c, Symbol: %s\n", address, type, sym);
if ( AddSymbol(address, sym) == 0 ) {
- Syslog(LOG_ERR, "Error adding symbol - %s.", sym);
+ imklogLogIntMsg(LOG_ERR, "Error adding symbol - %s.", sym);
fclose(sym_file);
return(0);
}
@@ -231,23 +229,24 @@ extern int InitKsyms(char *mapfile)
}
- Syslog(LOG_INFO, "Loaded %d symbols from %s.", num_syms, mapfile);
+ imklogLogIntMsg(LOG_INFO, "Loaded %d symbols from %s.", num_syms, mapfile);
switch(version) {
case -1:
- Syslog(LOG_WARNING, "Symbols do not match kernel version.");
+ imklogLogIntMsg(LOG_WARNING, "Symbols do not match kernel version.");
num_syms = 0;
break;
case 0:
- Syslog(LOG_WARNING, "Cannot verify that symbols match kernel version.");
+ imklogLogIntMsg(LOG_WARNING, "Cannot verify that symbols match kernel version.");
break;
case 1:
- Syslog(LOG_INFO, "Symbols match kernel version %s.", vstring);
+ imklogLogIntMsg(LOG_INFO, "Symbols match kernel version %s.", vstring);
break;
}
fclose(sym_file);
+ ENDfunc
return(1);
}
@@ -292,44 +291,42 @@ extern void DeinitKsyms(void)
**************************************************************************/
static char *FindSymbolFile(void)
{
- auto char *file = (char *) 0,
+ auto char *file = NULL,
**mf = system_maps;
-
auto struct utsname utsname;
- static char symfile[100];
-
- auto FILE *sym_file = (FILE *) 0;
+ static char mysymfile[100];
+ auto FILE *sym_file = NULL;
+ BEGINfunc
- if ( uname(&utsname) < 0 ) {
- Syslog(LOG_ERR, "Cannot get kernel version information.");
+ if(uname(&utsname) < 0) {
+ imklogLogIntMsg(LOG_ERR, "Cannot get kernel version information.");
return(0);
}
dbgprintf("Searching for symbol map.\n");
- for(mf = system_maps; *mf != (char *) 0 && file == (char *) 0; ++mf) {
-
- snprintf(symfile, sizeof(symfile), "%s-%s", *mf, utsname.release);
- dbgprintf("Trying %s.\n", symfile);
- if ( (sym_file = fopen(symfile, "r")) != (FILE *) 0 ) {
- if (CheckMapVersion(symfile) == 1)
- file = symfile;
+ for(mf = system_maps; *mf != NULL && file == NULL; ++mf) {
+ snprintf(mysymfile, sizeof(mysymfile), "%s-%s", *mf, utsname.release);
+ dbgprintf("Trying %s.\n", mysymfile);
+ if((sym_file = fopen(mysymfile, "r")) != NULL) {
+ if(CheckMapVersion(mysymfile) == 1)
+ file = mysymfile;
fclose(sym_file);
}
- if (sym_file == (FILE *) 0 || file == (char *) 0) {
- sprintf (symfile, "%s", *mf);
- dbgprintf("Trying %s.\n", symfile);
- if ( (sym_file = fopen(symfile, "r")) != (FILE *) 0 ) {
- if (CheckMapVersion(symfile) == 1)
- file = symfile;
+ if(sym_file == NULL || file == NULL) {
+ sprintf (mysymfile, "%s", *mf);
+ dbgprintf("Trying %s.\n", mysymfile);
+ if((sym_file = fopen(mysymfile, "r")) != NULL ) {
+ if (CheckMapVersion(mysymfile) == 1)
+ file = mysymfile;
fclose(sym_file);
}
}
-
}
/* At this stage of the game we are at the end of the symbol tables. */
dbgprintf("End of search list encountered.\n");
+ ENDfunc
return(file);
}
@@ -410,13 +407,13 @@ static int CheckVersion(char *version)
* version level.
*/
if ( uname(&utsname) < 0 ) {
- Syslog(LOG_ERR, "Cannot get kernel version information.");
+ imklogLogIntMsg(LOG_ERR, "Cannot get kernel version information.");
return(0);
}
dbgprintf("Comparing kernel %s with symbol table %s.\n", utsname.release, vstring);
if ( sscanf (utsname.release, "%d.%d.%d", &major, &minor, &patch) < 3 ) {
- Syslog(LOG_ERR, "Kernel send bogus release string `%s'.", utsname.release);
+ imklogLogIntMsg(LOG_ERR, "Kernel send bogus release string `%s'.", utsname.release);
return(0);
}
@@ -464,18 +461,18 @@ static int CheckMapVersion(char *fname)
auto char type,
sym[512];
- if ( (sym_file = fopen(fname, "r")) != (FILE *) 0 ) {
+ if ( (sym_file = fopen(fname, "r")) != NULL ) {
/*
* At this point a map file was successfully opened. We
* now need to search this file and look for version
* information.
*/
- Syslog(LOG_INFO, "Inspecting %s", fname);
+ imklogLogIntMsg(LOG_INFO, "Inspecting %s", fname);
version = 0;
while ( !feof(sym_file) && (version == 0) ) {
if ( fscanf(sym_file, "%lx %c %s\n", &address, &type, sym) != 3 ) {
- Syslog(LOG_ERR, "Error in symbol table input (#2).");
+ imklogLogIntMsg(LOG_ERR, "Error in symbol table input (#2).");
fclose(sym_file);
return(0);
}
@@ -487,7 +484,7 @@ static int CheckMapVersion(char *fname)
switch ( version ) {
case -1:
- Syslog(LOG_ERR, "Symbol table has incorrect version number.\n");
+ imklogLogIntMsg(LOG_ERR, "Symbol table has incorrect version number.\n");
break;
case 0:
dbgprintf("No version information found.\n");
@@ -527,7 +524,7 @@ static int AddSymbol(unsigned long address, char *symbol)
/* Then the space for the symbol. */
sym_array[num_syms].name = (char *) malloc(strlen(symbol)*sizeof(char) + 1);
- if ( sym_array[num_syms].name == (char *) 0 )
+ if ( sym_array[num_syms].name == NULL )
return(0);
sym_array[num_syms].value = address;
@@ -566,13 +563,13 @@ char * LookupSymbol(unsigned long value, struct symbol *sym)
struct symbol ksym, msym;
if (!sym_array)
- return((char *) 0);
+ return(NULL);
last = sym_array[0].name;
ksym.offset = 0;
ksym.size = 0;
if ( value < sym_array[0].value )
- return((char *) 0);
+ return(NULL);
for(lp = 0; lp <= num_syms; ++lp) {
if ( sym_array[lp].value > value ) {
@@ -587,7 +584,7 @@ char * LookupSymbol(unsigned long value, struct symbol *sym)
name = LookupModuleSymbol(value, &msym);
if ( ksym.offset == 0 && msym.offset == 0 ) {
- return((char *) 0);
+ return(NULL);
}
if ( ksym.offset == 0 || msym.offset < 0 ||
@@ -602,7 +599,7 @@ char * LookupSymbol(unsigned long value, struct symbol *sym)
}
- return((char *) 0);
+ return(NULL);
}
/**************************************************************************
@@ -683,8 +680,8 @@ extern char *ExpandKadds(char *line, char *el)
* open for patches.
*/
if ( i_am_paranoid &&
- (strstr(line, "Oops:") != (char *) 0) && !InitMsyms() )
- Syslog(LOG_WARNING, "Cannot load kernel module symbols.\n");
+ (strstr(line, "Oops:") != NULL) && !InitMsyms() )
+ imklogLogIntMsg(LOG_WARNING, "Cannot load kernel module symbols.\n");
/*
@@ -692,7 +689,7 @@ extern char *ExpandKadds(char *line, char *el)
* messages in this line.
*/
if ( (num_syms == 0) ||
- (kp = strstr(line, "[<")) == (char *) 0 ) {
+ (kp = strstr(line, "[<")) == NULL ) {
#ifdef __sparc__
if (num_syms) {
/* On SPARC, register dumps do not have the [< >] characters in it.
@@ -780,7 +777,7 @@ extern char *ExpandKadds(char *line, char *el)
*elp++ = *sl++;
/* Now poised at a kernel delimiter. */
- if ( (kp = strstr(sl, ">]")) == (char *) 0 ) {
+ if ( (kp = strstr(sl, ">]")) == NULL ) {
strcpy(el, sl);
return(el);
}
@@ -788,7 +785,7 @@ extern char *ExpandKadds(char *line, char *el)
strncpy(num,sl+1,kp-sl-1);
num[kp-sl-1] = '\0';
value = strtoul(num, (char **) 0, 16);
- if ( (symbol = LookupSymbol(value, &sym)) == (char *) 0 )
+ if ( (symbol = LookupSymbol(value, &sym)) == NULL )
symbol = sl;
strcat(elp, symbol);
@@ -805,10 +802,10 @@ extern char *ExpandKadds(char *line, char *el)
strncat(elp, kp, value);
elp += value;
sl = kp + value;
- if ( (kp = strstr(sl, "[<")) == (char *) 0 )
+ if ( (kp = strstr(sl, "[<")) == NULL )
strcat(elp, sl);
}
- while ( kp != (char *) 0);
+ while ( kp != NULL);
dbgprintf("Expanded line: %s\n", el);
return(el);
diff --git a/plugins/imklog/ksym_mod.c b/plugins/imklog/ksym_mod.c
index 3e064e2..6e48e89 100644
--- a/plugins/imklog/ksym_mod.c
+++ b/plugins/imklog/ksym_mod.c
@@ -158,10 +158,10 @@ extern int InitMsyms(void)
if ( ksyms == NULL ) {
if ( errno == ENOENT )
- Syslog(LOG_INFO, "No module symbols loaded - "
+ imklogLogIntMsg(LOG_INFO, "No module symbols loaded - "
"kernel modules not enabled.\n");
else
- Syslog(LOG_ERR, "Error loading kernel symbols " \
+ imklogLogIntMsg(LOG_ERR, "Error loading kernel symbols " \
"- %s\n", strerror(errno));
return(0);
}
@@ -200,9 +200,9 @@ extern int InitMsyms(void)
}
if ( rtn == 0 )
- Syslog(LOG_INFO, "No module symbols loaded.");
+ imklogLogIntMsg(LOG_INFO, "No module symbols loaded.");
else
- Syslog(LOG_INFO, "Loaded %d %s from %d module%s", rtn, \
+ imklogLogIntMsg(LOG_INFO, "Loaded %d %s from %d module%s", rtn, \
(rtn == 1) ? "symbol" : "symbols", \
num_modules, (num_modules == 1) ? "." : "s.");
@@ -295,7 +295,7 @@ struct Module *AddModule(module)
if ( sym_array_modules == NULL )
{
- Syslog(LOG_WARNING, "Cannot allocate Module array.\n");
+ imklogLogIntMsg(LOG_WARNING, "Cannot allocate Module array.\n");
return NULL;
}
mp = sym_array_modules;
@@ -307,7 +307,7 @@ struct Module *AddModule(module)
if ( mp == NULL )
{
- Syslog(LOG_WARNING, "Cannot allocate Module array.\n");
+ imklogLogIntMsg(LOG_WARNING, "Cannot allocate Module array.\n");
return NULL;
}
diff --git a/plugins/imklog/linux.c b/plugins/imklog/linux.c
new file mode 100644
index 0000000..faf2013
--- /dev/null
+++ b/plugins/imklog/linux.c
@@ -0,0 +1,544 @@
+/* klog for linux, based on the FreeBSD syslogd implementation.
+ *
+ * This contains OS-specific functionality to read the BSD
+ * kernel log. For a general overview, see head comment in
+ * imklog.c.
+ *
+ * This file heavily borrows from the klogd daemon provided by
+ * the sysklogd project. Many thanks for this piece of software.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Rsyslog is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+*/
+#include "config.h"
+#include "rsyslog.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <signal.h>
+#include <string.h>
+#include <pthread.h>
+#include "syslogd.h"
+#include "cfsysline.h"
+#include "template.h"
+#include "msg.h"
+#include "module-template.h"
+#include "imklog.h"
+
+
+/* Includes. */
+#include <unistd.h>
+#include <errno.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+
+#if HAVE_TIME_H
+# include <time.h>
+#endif
+
+#include <stdarg.h>
+#include <paths.h>
+#include "ksyms.h"
+
+#define __LIBRARY__
+#include <unistd.h>
+
+
+#if !defined(__GLIBC__)
+# define __NR_ksyslog __NR_syslog
+_syscall3(int,ksyslog,int, type, char *, buf, int, len);
+#else
+#include <sys/klog.h>
+#define ksyslog klogctl
+#endif
+
+
+
+#ifndef _PATH_KLOG
+#define _PATH_KLOG "/proc/kmsg"
+#endif
+
+#define LOG_BUFFER_SIZE 4096
+#define LOG_LINE_LENGTH 1000
+
+static int kmsg;
+static char log_buffer[LOG_BUFFER_SIZE];
+
+static enum LOGSRC {none, proc, kernel} logsrc;
+
+
+/* Function prototypes. */
+extern int ksyslog(int type, char *buf, int len);
+
+
+static void CloseLogSrc(void)
+{
+ /* Turn on logging of messages to console, but only if we had the -c
+ * option -- rgerhards, 2007-08-01
+ */
+ if (console_log_level != -1)
+ ksyslog(7, NULL, 0);
+
+ /* Shutdown the log sources. */
+ switch ( logsrc )
+ {
+ case kernel:
+ ksyslog(0, 0, 0);
+ imklogLogIntMsg(LOG_INFO, "Kernel logging (ksyslog) stopped.");
+ break;
+ case proc:
+ close(kmsg);
+ imklogLogIntMsg(LOG_INFO, "Kernel logging (proc) stopped.");
+ break;
+ case none:
+ break;
+ }
+
+ return;
+}
+
+
+static enum LOGSRC GetKernelLogSrc(void)
+{
+ auto struct stat sb;
+
+ /* Set level of kernel console messaging.. */
+ if ( (console_log_level != -1) &&
+ (ksyslog(8, NULL, console_log_level) < 0) &&
+ (errno == EINVAL) )
+ {
+ /*
+ * An invalid arguement error probably indicates that
+ * a pre-0.14 kernel is being run. At this point we
+ * issue an error message and simply shut-off console
+ * logging completely.
+ */
+ imklogLogIntMsg(LOG_WARNING, "Cannot set console log level - disabling "
+ "console output.");
+ }
+
+ /*
+ * First do a stat to determine whether or not the proc based
+ * file system is available to get kernel messages from.
+ */
+ if ( use_syscall ||
+ ((stat(_PATH_KLOG, &sb) < 0) && (errno == ENOENT)) )
+ {
+ /* Initialize kernel logging. */
+ ksyslog(1, NULL, 0);
+ imklogLogIntMsg(LOG_INFO, "imklog %s, log source = ksyslog "
+ "started.", VERSION);
+ return(kernel);
+ }
+
+ if ( (kmsg = open(_PATH_KLOG, O_RDONLY)) < 0 )
+ {
+ char sz[512];
+ snprintf(sz, sizeof(sz), "imklog: Cannot open proc file system, %d - %s.\n", errno, strerror(errno));
+ logmsgInternal(LOG_SYSLOG|LOG_ERR, sz, ADDDATE);
+ ksyslog(7, NULL, 0); /* TODO: check this, implement more */
+ return(none);
+ }
+
+ imklogLogIntMsg(LOG_INFO, "imklog %s, log source = %s started.", VERSION, _PATH_KLOG);
+ return(proc);
+}
+
+
+/* Copy characters from ptr to line until a char in the delim
+ * string is encountered or until min( space, len ) chars have
+ * been copied.
+ *
+ * Returns the actual number of chars copied.
+ */
+static int copyin( uchar *line, int space,
+ const char *ptr, int len,
+ const char *delim )
+{
+ auto int i;
+ auto int count;
+
+ count = len < space ? len : space;
+
+ for(i=0; i<count && !strchr(delim, *ptr); i++ ) {
+ *line++ = *ptr++;
+ }
+
+ return(i);
+}
+
+/*
+ * Messages are separated by "\n". Messages longer than
+ * LOG_LINE_LENGTH are broken up.
+ *
+ * Kernel symbols show up in the input buffer as : "[<aaaaaa>]",
+ * where "aaaaaa" is the address. These are replaced with
+ * "[symbolname+offset/size]" in the output line - symbolname,
+ * offset, and size come from the kernel symbol table.
+ *
+ * If a kernel symbol happens to fall at the end of a message close
+ * in length to LOG_LINE_LENGTH, the symbol will not be expanded.
+ * (This should never happen, since the kernel should never generate
+ * messages that long.
+ *
+ * To preserve the original addresses, lines containing kernel symbols
+ * are output twice. Once with the symbols converted and again with the
+ * original text. Just in case somebody wants to run their own Oops
+ * analysis on the syslog, e.g. ksymoops.
+ */
+static void LogLine(char *ptr, int len)
+{
+ enum parse_state_enum {
+ PARSING_TEXT,
+ PARSING_SYMSTART, /* at < */
+ PARSING_SYMBOL,
+ PARSING_SYMEND /* at ] */
+ };
+
+ static uchar line_buff[LOG_LINE_LENGTH];
+
+ static uchar *line =line_buff;
+ static enum parse_state_enum parse_state = PARSING_TEXT;
+ static int space = sizeof(line_buff)-1;
+
+ static uchar *sym_start; /* points at the '<' of a symbol */
+
+ auto int delta = 0; /* number of chars copied */
+ auto int symbols_expanded = 0; /* 1 if symbols were expanded */
+ auto int skip_symbol_lookup = 0; /* skip symbol lookup on this pass */
+ auto char *save_ptr = ptr; /* save start of input line */
+ auto int save_len = len; /* save length at start of input line */
+
+ while( len > 0 )
+ {
+ if( space == 0 ) /* line buffer is full */
+ {
+ /*
+ ** Line too long. Start a new line.
+ */
+ *line = 0; /* force null terminator */
+
+ //dbgprintf("Line buffer full:\n");
+ //dbgprintf("\tLine: %s\n", line);
+
+ Syslog(LOG_INFO, line_buff);
+ line = line_buff;
+ space = sizeof(line_buff)-1;
+ parse_state = PARSING_TEXT;
+ symbols_expanded = 0;
+ skip_symbol_lookup = 0;
+ save_ptr = ptr;
+ save_len = len;
+ }
+
+ switch( parse_state )
+ {
+ case PARSING_TEXT:
+ delta = copyin(line, space, ptr, len, "\n[" );
+ line += delta;
+ ptr += delta;
+ space -= delta;
+ len -= delta;
+
+ if( space == 0 || len == 0 )
+ {
+ break; /* full line_buff or end of input buffer */
+ }
+
+ if( *ptr == '\0' ) /* zero byte */
+ {
+ ptr++; /* skip zero byte */
+ space -= 1;
+ len -= 1;
+
+ break;
+ }
+
+ if( *ptr == '\n' ) /* newline */
+ {
+ ptr++; /* skip newline */
+ space -= 1;
+ len -= 1;
+
+ *line = 0; /* force null terminator */
+ Syslog(LOG_INFO, line_buff);
+ line = line_buff;
+ space = sizeof(line_buff)-1;
+ if (symbols_twice) {
+ if (symbols_expanded) {
+ /* reprint this line without symbol lookup */
+ symbols_expanded = 0;
+ skip_symbol_lookup = 1;
+ ptr = save_ptr;
+ len = save_len;
+ }
+ else
+ {
+ skip_symbol_lookup = 0;
+ save_ptr = ptr;
+ save_len = len;
+ }
+ }
+ break;
+ }
+ if( *ptr == '[' ) /* possible kernel symbol */
+ {
+ *line++ = *ptr++;
+ space -= 1;
+ len -= 1;
+ if (!skip_symbol_lookup)
+ parse_state = PARSING_SYMSTART; /* at < */
+ break;
+ }
+ /* Now that line_buff is no longer fed to *printf as format
+ * string, '%'s are no longer "dangerous".
+ */
+ break;
+
+ case PARSING_SYMSTART:
+ if( *ptr != '<' )
+ {
+ parse_state = PARSING_TEXT; /* not a symbol */
+ break;
+ }
+
+ /*
+ ** Save this character for now. If this turns out to
+ ** be a valid symbol, this char will be replaced later.
+ ** If not, we'll just leave it there.
+ */
+
+ sym_start = line; /* this will point at the '<' */
+
+ *line++ = *ptr++;
+ space -= 1;
+ len -= 1;
+ parse_state = PARSING_SYMBOL; /* symbol... */
+ break;
+
+ case PARSING_SYMBOL:
+ delta = copyin( line, space, ptr, len, ">\n[" );
+ line += delta;
+ ptr += delta;
+ space -= delta;
+ len -= delta;
+ if( space == 0 || len == 0 )
+ {
+ break; /* full line_buff or end of input buffer */
+ }
+ if( *ptr != '>' )
+ {
+ parse_state = PARSING_TEXT;
+ break;
+ }
+
+ *line++ = *ptr++; /* copy the '>' */
+ space -= 1;
+ len -= 1;
+
+ parse_state = PARSING_SYMEND;
+
+ break;
+
+ case PARSING_SYMEND:
+ if( *ptr != ']' )
+ {
+ parse_state = PARSING_TEXT; /* not a symbol */
+ break;
+ }
+
+ /*
+ ** It's really a symbol! Replace address with the
+ ** symbol text.
+ */
+ {
+ auto int sym_space;
+
+ unsigned long value;
+ auto struct symbol sym;
+ auto char *symbol;
+
+ *(line-1) = 0; /* null terminate the address string */
+ value = strtoul((char*)(sym_start+1), (char **) 0, 16);
+ *(line-1) = '>'; /* put back delim */
+
+ if ( !symbol_lookup || (symbol = LookupSymbol(value, &sym)) == (char *)0 )
+ {
+ parse_state = PARSING_TEXT;
+ break;
+ }
+
+ /*
+ ** verify there is room in the line buffer
+ */
+ sym_space = space + ( line - sym_start );
+ if( (unsigned) sym_space < strlen(symbol) + 30 ) /*(30 should be overkill)*/
+ {
+ parse_state = PARSING_TEXT; /* not enough space */
+ break;
+ }
+
+ // TODO: sprintf!!!!
+ delta = sprintf( (char*) sym_start, "%s+%d/%d]",
+ symbol, sym.offset, sym.size );
+
+ space = sym_space + delta;
+ line = sym_start + delta;
+ symbols_expanded = 1;
+ }
+ ptr++;
+ len--;
+ parse_state = PARSING_TEXT;
+ break;
+
+ default: /* Can't get here! */
+ parse_state = PARSING_TEXT;
+
+ }
+ }
+
+ return;
+}
+
+
+static void LogKernelLine(void)
+{
+ auto int rdcnt;
+
+ /*
+ * Zero-fill the log buffer. This should cure a multitude of
+ * problems with klogd logging the tail end of the message buffer
+ * which will contain old messages. Then read the kernel log
+ * messages into this fresh buffer.
+ */
+ memset(log_buffer, '\0', sizeof(log_buffer));
+ if ( (rdcnt = ksyslog(2, log_buffer, sizeof(log_buffer)-1)) < 0 )
+ {
+ char sz[512];
+ if(errno == EINTR)
+ return;
+ snprintf(sz, sizeof(sz), "imklog: Error return from sys_sycall: %d - %s\n", errno, strerror(errno));
+ logmsgInternal(LOG_SYSLOG|LOG_ERR, sz, ADDDATE);
+ }
+ else
+ LogLine(log_buffer, rdcnt);
+ return;
+}
+
+
+static void LogProcLine(void)
+{
+ auto int rdcnt;
+
+ /*
+ * Zero-fill the log buffer. This should cure a multitude of
+ * problems with klogd logging the tail end of the message buffer
+ * which will contain old messages. Then read the kernel messages
+ * from the message pseudo-file into this fresh buffer.
+ */
+ memset(log_buffer, '\0', sizeof(log_buffer));
+ if ( (rdcnt = read(kmsg, log_buffer, sizeof(log_buffer)-1)) < 0 ) {
+ if ( errno == EINTR )
+ return;
+ imklogLogIntMsg(LOG_ERR, "Cannot read proc file system: %d - %s.", errno, strerror(errno));
+ } else {
+ LogLine(log_buffer, rdcnt);
+ }
+
+ return;
+}
+
+
+/* to be called in the module's WillRun entry point
+ * rgerhards, 2008-04-09
+ */
+rsRetVal klogLogKMsg(void)
+{
+ DEFiRet;
+ switch(logsrc) {
+ case kernel:
+ LogKernelLine();
+ break;
+ case proc:
+ LogProcLine();
+ break;
+ case none:
+ /* TODO: We need to handle this case here somewhat more intelligent
+ * This is now at least partly done - code should never reach this point
+ * as willRun() already checked for the "none" status -- rgerhards, 2007-12-17
+ */
+ pause();
+ break;
+ }
+ RETiRet;
+}
+
+
+/* to be called in the module's WillRun entry point
+ * rgerhards, 2008-04-09
+ */
+rsRetVal klogWillRun(void)
+{
+ DEFiRet;
+ /* Initialize this module. If that fails, we tell the engine we don't like to run */
+ /* Determine where kernel logging information is to come from. */
+ logsrc = GetKernelLogSrc();
+ if(logsrc == none) {
+ iRet = RS_RET_NO_KERNEL_LOGSRC;
+ } else {
+ if (symbol_lookup) {
+ symbol_lookup = (InitKsyms(symfile) == 1);
+ symbol_lookup |= InitMsyms();
+ if (symbol_lookup == 0) {
+ imklogLogIntMsg(LOG_WARNING, "cannot find any symbols, turning off symbol lookups");
+ }
+ }
+ }
+
+ RETiRet;
+}
+
+
+/* to be called in the module's AfterRun entry point
+ * rgerhards, 2008-04-09
+ */
+rsRetVal klogAfterRun(void)
+{
+ DEFiRet;
+ /* cleanup here */
+ if(logsrc != none)
+ CloseLogSrc();
+
+ DeinitKsyms();
+ DeinitMsyms();
+
+ RETiRet;
+}
+
+
+/* provide the (system-specific) default facility for internal messages
+ * rgerhards, 2008-04-14
+ */
+int
+klogFacilIntMsg(void)
+{
+ return LOG_KERN;
+}
+
+
+/* vi:set ai:
+ */
diff --git a/plugins/immark/immark.c b/plugins/immark/immark.c
index 30118de..0bc3199 100644
--- a/plugins/immark/immark.c
+++ b/plugins/immark/immark.c
@@ -84,6 +84,8 @@ ENDrunInput
BEGINwillRun
CODESTARTwillRun
+ /* We set the global MarkInterval to what is configured here -- rgerhards, 2008-07-15 */
+ MarkInterval = iMarkMessagePeriod;
if(iMarkMessagePeriod == 0)
iRet = RS_RET_NO_RUN;
ENDwillRun
diff --git a/plugins/imuxsock/imuxsock.c b/plugins/imuxsock/imuxsock.c
index 3cdcbf0..f879803 100644
--- a/plugins/imuxsock/imuxsock.c
+++ b/plugins/imuxsock/imuxsock.c
@@ -181,7 +181,7 @@ static rsRetVal readSocket(int fd, int bParseHost, int flags)
iRcvd = recv(fd, line, MAXLINE - 1, 0);
dbgprintf("Message from UNIX socket: #%d\n", fd);
if (iRcvd > 0) {
- parseAndSubmitMessage(LocalHostName, line, iRcvd, bParseHost, flags, eFLOWCTL_LIGHT_DELAY);
+ parseAndSubmitMessage((char*)LocalHostName, line, iRcvd, bParseHost, flags, eFLOWCTL_LIGHT_DELAY);
} else if (iRcvd < 0 && errno != EINTR) {
char errStr[1024];
rs_strerror_r(errno, errStr, sizeof(errStr));
diff --git a/plugins/omgssapi/omgssapi.c b/plugins/omgssapi/omgssapi.c
index be05177..34abfe0 100644
--- a/plugins/omgssapi/omgssapi.c
+++ b/plugins/omgssapi/omgssapi.c
@@ -4,7 +4,7 @@
* NOTE: read comments in module-template.h to understand how this file
* works!
*
- * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of rsyslog.
*
@@ -79,7 +79,7 @@ DEFobjCurrIf(gssutil)
DEFobjCurrIf(tcpclt)
typedef struct _instanceData {
- char f_hname[MAXHOSTNAMELEN+1];
+ char *f_hname;
short sock; /* file descriptor */
enum { /* TODO: we shoud revisit these definitions */
eDestFORW,
@@ -162,6 +162,9 @@ CODESTARTfreeInstance
tcpclt.Destruct(&pData->pTCPClt);
if(pData->sock >= 0)
close(pData->sock);
+
+ if(pData->f_hname != NULL)
+ free(pData->f_hname);
ENDfreeInstance
@@ -551,7 +554,7 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1)
/* extract the host first (we do a trick - we replace the ';' or ':' with a '\0')
* now skip to port and then template name. rgerhards 2005-07-06
*/
- for(q = p ; *p && *p != ';' && *p != ':' ; ++p)
+ for(q = p ; *p && *p != ';' && *p != ':' && *p != '#' ; ++p)
/* JUST SKIP */;
pData->port = NULL;
@@ -575,27 +578,21 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1)
}
}
+
/* now skip to template */
bErr = 0;
- while(*p && *p != ';') {
- if(*p && *p != ';' && !isspace((int) *p)) {
- if(bErr == 0) { /* only 1 error msg! */
- bErr = 1;
- errno = 0;
- errmsg.LogError(NO_ERRCODE, "invalid selector line (port), probably not doing "
- "what was intended");
- }
- }
- ++p;
- }
+ while(*p && *p != ';' && *p != '#' && !isspace((int) *p))
+ ++p; /*JUST SKIP*/
/* TODO: make this if go away! */
- if(*p == ';') {
+ if(*p == ';' || *p == '#' || isspace(*p)) {
+ uchar cTmp = *p;
*p = '\0'; /* trick to obtain hostname (later)! */
- strcpy(pData->f_hname, (char*) q);
- *p = ';';
- } else
- strcpy(pData->f_hname, (char*) q);
+ CHKmalloc(pData->f_hname = strdup((char*) q));
+ *p = cTmp;
+ } else {
+ CHKmalloc(pData->f_hname = strdup((char*) q));
+ }
/* process template */
CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS,
@@ -701,6 +698,5 @@ CODEmodInit_QueryRegCFSLineHdlr
ENDmodInit
#endif /* #ifdef USE_GSSAPI */
-/*
- * vi:set ai:
+/* vi:set ai:
*/
diff --git a/plugins/ommail/Makefile.am b/plugins/ommail/Makefile.am
new file mode 100644
index 0000000..7e9f5f1
--- /dev/null
+++ b/plugins/ommail/Makefile.am
@@ -0,0 +1,6 @@
+pkglib_LTLIBRARIES = ommail.la
+
+ommail_la_SOURCES = ommail.c
+ommail_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags)
+ommail_la_LDFLAGS = -module -avoid-version
+ommail_la_LIBADD =
diff --git a/plugins/ommail/Makefile.in b/plugins/ommail/Makefile.in
new file mode 100644
index 0000000..8fe419a
--- /dev/null
+++ b/plugins/ommail/Makefile.in
@@ -0,0 +1,494 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = plugins/ommail
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(pkglibdir)"
+pkglibLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+ommail_la_DEPENDENCIES =
+am_ommail_la_OBJECTS = ommail_la-ommail.lo
+ommail_la_OBJECTS = $(am_ommail_la_OBJECTS)
+ommail_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(ommail_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(ommail_la_SOURCES)
+DIST_SOURCES = $(ommail_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GREP = @GREP@
+HAVE_MYSQL_CONFIG = @HAVE_MYSQL_CONFIG@
+HAVE_PGSQL_CONFIG = @HAVE_PGSQL_CONFIG@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dl_libs = @dl_libs@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gss_libs = @gss_libs@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdbi_cflags = @libdbi_cflags@
+libdbi_libs = @libdbi_libs@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+mysql_cflags = @mysql_cflags@
+mysql_libs = @mysql_libs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pgsql_cflags = @pgsql_cflags@
+pgsql_libs = @pgsql_libs@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pthreads_cflags = @pthreads_cflags@
+pthreads_libs = @pthreads_libs@
+rfc3195_cflags = @rfc3195_cflags@
+rfc3195_libs = @rfc3195_libs@
+rt_libs = @rt_libs@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+snmp_cflags = @snmp_cflags@
+snmp_libs = @snmp_libs@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+zlib_libs = @zlib_libs@
+pkglib_LTLIBRARIES = ommail.la
+ommail_la_SOURCES = ommail.c
+ommail_la_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags)
+ommail_la_LDFLAGS = -module -avoid-version
+ommail_la_LIBADD =
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/ommail/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu plugins/ommail/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(pkglibdir)" || $(MKDIR_P) "$(DESTDIR)$(pkglibdir)"
+ @list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pkglibLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(pkglibdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pkglibLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(pkglibdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-pkglibLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$p'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$p"; \
+ done
+
+clean-pkglibLTLIBRARIES:
+ -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES)
+ @list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+ommail.la: $(ommail_la_OBJECTS) $(ommail_la_DEPENDENCIES)
+ $(ommail_la_LINK) -rpath $(pkglibdir) $(ommail_la_OBJECTS) $(ommail_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ommail_la-ommail.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+ommail_la-ommail.lo: ommail.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ommail_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ommail_la-ommail.lo -MD -MP -MF $(DEPDIR)/ommail_la-ommail.Tpo -c -o ommail_la-ommail.lo `test -f 'ommail.c' || echo '$(srcdir)/'`ommail.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ommail_la-ommail.Tpo $(DEPDIR)/ommail_la-ommail.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ommail.c' object='ommail_la-ommail.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ommail_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ommail_la-ommail.lo `test -f 'ommail.c' || echo '$(srcdir)/'`ommail.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-pkglibLTLIBRARIES
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pkglibLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pkglibLTLIBRARIES \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-pkglibLTLIBRARIES
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/ommail/ommail.c b/plugins/ommail/ommail.c
new file mode 100644
index 0000000..218c73c
--- /dev/null
+++ b/plugins/ommail/ommail.c
@@ -0,0 +1,630 @@
+/* ommail.c
+ *
+ * This is an implementation of a mail sending output module. So far, we
+ * only support direct SMTP, that is talking to a SMTP server. In the long
+ * term, support for using sendmail should also be implemented. Please note
+ * that the SMTP protocol implementation is a very bare one. We support
+ * RFC821/822 messages, without any authentication and any other nice
+ * features (no MIME, no nothing). It is assumed that proper firewalling
+ * and/or STMP server configuration is used together with this module.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2008-04-04 by RGerhards
+ *
+ * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Rsyslog is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <time.h>
+#include <sys/socket.h>
+#include "syslogd.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "errmsg.h"
+
+MODULE_TYPE_OUTPUT
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(errmsg)
+
+static uchar *pszSrv = NULL;
+static uchar *pszSrvPort = NULL;
+static uchar *pszFrom = NULL;
+static uchar *pszTo = NULL;
+static uchar *pszSubject = NULL;
+static int bEnableBody = 1; /* should a mail body be generated? (set to 0 eg for SMS gateways) */
+
+typedef struct _instanceData {
+ int iMode; /* 0 - smtp, 1 - sendmail */
+ int bHaveSubject; /* is a subject configured? (if so, it is the second string provided by rsyslog core) */
+ int bEnableBody; /* is a body configured? (if so, it is the second string provided by rsyslog core) */
+ union {
+ struct {
+ uchar *pszSrv;
+ uchar *pszSrvPort;
+ uchar *pszFrom;
+ uchar *pszTo;
+ char RcvBuf[1024]; /* buffer for receiving server responses */
+ size_t lenRcvBuf;
+ size_t iRcvBuf; /* current index into the rcvBuf (buf empty if iRcvBuf == lenRcvBuf) */
+ int sock; /* socket to this server (most important when we do multiple msgs per mail) */
+ } smtp;
+ } md; /* mode-specific data */
+} instanceData;
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ if(pData->iMode == 0) {
+ if(pData->md.smtp.pszSrv != NULL)
+ free(pData->md.smtp.pszSrv);
+ if(pData->md.smtp.pszSrvPort != NULL)
+ free(pData->md.smtp.pszSrvPort);
+ if(pData->md.smtp.pszFrom != NULL)
+ free(pData->md.smtp.pszFrom);
+ if(pData->md.smtp.pszTo != NULL)
+ free(pData->md.smtp.pszTo);
+ }
+ENDfreeInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ printf("mail"); /* TODO: extend! */
+ENDdbgPrintInstInfo
+
+
+/* TCP support code, should probably be moved to net.c or some place else... -- rgerhards, 2008-04-04 */
+
+/* "receive" a character from the remote server. A single character
+ * is returned. Returns RS_RET_NO_MORE_DATA if the server has closed
+ * the connection and RS_RET_IO_ERROR if something goes wrong. This
+ * is a blocking read.
+ * rgerhards, 2008-04-04
+ */
+static rsRetVal
+getRcvChar(instanceData *pData, char *pC)
+{
+ DEFiRet;
+ ssize_t lenBuf;
+ assert(pData != NULL);
+
+ if(pData->md.smtp.iRcvBuf == pData->md.smtp.lenRcvBuf) { /* buffer empty? */
+ /* yes, we need to read the next server response */
+ do {
+ lenBuf = recv(pData->md.smtp.sock, pData->md.smtp.RcvBuf, sizeof(pData->md.smtp.RcvBuf), 0);
+ if(lenBuf == 0) {
+ ABORT_FINALIZE(RS_RET_NO_MORE_DATA);
+ } else if(lenBuf < 0) {
+ if(errno != EAGAIN) {
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+ } else {
+ /* good read */
+ pData->md.smtp.iRcvBuf = 0;
+ pData->md.smtp.lenRcvBuf = lenBuf;
+ }
+
+ } while(lenBuf < 1);
+ }
+
+ /* when we reach this point, we have a non-empty buffer */
+ *pC = pData->md.smtp.RcvBuf[pData->md.smtp.iRcvBuf++];
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* close the mail server connection
+ * rgerhards, 2008-04-08
+ */
+static rsRetVal
+serverDisconnect(instanceData *pData)
+{
+ DEFiRet;
+ assert(pData != NULL);
+
+ if(pData->md.smtp.sock != -1) {
+ close(pData->md.smtp.sock);
+ pData->md.smtp.sock = -1;
+ }
+
+ RETiRet;
+}
+
+
+/* open a connection to the mail server
+ * rgerhards, 2008-04-04
+ */
+static rsRetVal
+serverConnect(instanceData *pData)
+{
+ struct addrinfo *res = NULL;
+ struct addrinfo hints;
+ char *smtpPort;
+ char *smtpSrv;
+ char errStr[1024];
+
+ DEFiRet;
+ assert(pData != NULL);
+
+ if(pData->md.smtp.pszSrv == NULL)
+ smtpSrv = "127.0.0.1";
+ else
+ smtpSrv = (char*)pData->md.smtp.pszSrv;
+
+ if(pData->md.smtp.pszSrvPort == NULL)
+ smtpPort = "25";
+ else
+ smtpPort = (char*)pData->md.smtp.pszSrvPort;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC; /* TODO: make configurable! */
+ hints.ai_socktype = SOCK_STREAM;
+ if(getaddrinfo(smtpSrv, smtpPort, &hints, &res) != 0) {
+ dbgprintf("error %d in getaddrinfo\n", errno);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ if((pData->md.smtp.sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) {
+ dbgprintf("couldn't create send socket, reason %s", rs_strerror_r(errno, errStr, sizeof(errStr)));
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ if(connect(pData->md.smtp.sock, res->ai_addr, res->ai_addrlen) != 0) {
+ dbgprintf("create tcp connection failed, reason %s", rs_strerror_r(errno, errStr, sizeof(errStr)));
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+finalize_it:
+ if(res != NULL)
+ freeaddrinfo(res);
+
+ if(iRet != RS_RET_OK) {
+ if(pData->md.smtp.sock != -1) {
+ close(pData->md.smtp.sock);
+ pData->md.smtp.sock = -1;
+ }
+ }
+
+ RETiRet;
+}
+
+
+/* send text to the server, blocking send */
+static rsRetVal
+Send(int sock, char *msg, size_t len)
+{
+ DEFiRet;
+ size_t offsBuf = 0;
+ ssize_t lenSend;
+
+ assert(msg != NULL);
+
+ if(len == 0) /* it's valid, but does not make much sense ;) */
+ FINALIZE;
+
+ do {
+ lenSend = send(sock, msg + offsBuf, len - offsBuf, 0);
+ if(lenSend == -1) {
+ if(errno != EAGAIN) {
+ dbgprintf("message not (tcp)send, errno %d", errno);
+ ABORT_FINALIZE(RS_RET_TCP_SEND_ERROR);
+ }
+ } else if(lenSend != (ssize_t) len) {
+ offsBuf += len; /* on to next round... */
+ } else {
+ FINALIZE;
+ }
+ } while(1);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* send body text to the server, blocking send
+ * The body is special in that we must escape a leading dot inside a line
+ */
+static rsRetVal
+bodySend(instanceData *pData, char *msg, size_t len)
+{
+ DEFiRet;
+ char szBuf[2048];
+ size_t iSrc;
+ size_t iBuf = 0;
+ int bHadCR = 0;
+ int bInStartOfLine = 1;
+
+ assert(pData != NULL);
+ assert(msg != NULL);
+
+ for(iSrc = 0 ; iSrc < len ; ++iSrc) {
+ if(iBuf >= sizeof(szBuf) - 1) { /* one is reserved for our extra dot */
+ CHKiRet(Send(pData->md.smtp.sock, szBuf, iBuf));
+ iBuf = 0;
+ }
+ szBuf[iBuf++] = msg[iSrc];
+ switch(msg[iSrc]) {
+ case '\r':
+ bHadCR = 1;
+ break;
+ case '\n':
+ if(bHadCR)
+ bInStartOfLine = 1;
+ bHadCR = 0;
+ break;
+ case '.':
+ if(bInStartOfLine)
+ szBuf[iBuf++] = '.'; /* space is always reserved for this! */
+ /*FALLTHROUGH*/
+ default:
+ bInStartOfLine = 0;
+ bHadCR = 0;
+ break;
+ }
+ }
+
+ if(iBuf > 0) { /* incomplete buffer to send (the *usual* case)? */
+ CHKiRet(Send(pData->md.smtp.sock, szBuf, iBuf));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* read response line from server
+ */
+static rsRetVal
+readResponseLn(instanceData *pData, char *pLn, size_t lenLn)
+{
+ DEFiRet;
+ size_t i = 0;
+ char c;
+
+ assert(pData != NULL);
+ assert(pLn != NULL);
+
+ do {
+ CHKiRet(getRcvChar(pData, &c));
+ if(c == '\n')
+ break;
+ if(i < (lenLn - 1)) /* if line is too long, we simply discard the rest */
+ pLn[i++] = c;
+ } while(1);
+ pLn[i] = '\0';
+ dbgprintf("smtp server response: %s\n", pLn); /* do not remove, this is helpful in troubleshooting SMTP probs! */
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* read numerical response code from server and compare it to requried response code.
+ * If they two don't match, return RS_RET_SMTP_ERROR.
+ * rgerhards, 2008-04-07
+ */
+static rsRetVal
+readResponse(instanceData *pData, int *piState, int iExpected)
+{
+ DEFiRet;
+ int bCont;
+ char buf[128];
+
+ assert(pData != NULL);
+ assert(piState != NULL);
+
+ bCont = 1;
+ do {
+ CHKiRet(readResponseLn(pData, buf, sizeof(buf)));
+ /* note: the code below is not 100% clean as we may have received less than 4 characters.
+ * However, as we have a fixed size this will not create a vulnerability. An error will
+ * also most likely be generated, so it is quite acceptable IMHO -- rgerhards, 2008-04-08
+ */
+ if(buf[3] != '-') { /* last or only response line? */
+ bCont = 0;
+ *piState = buf[0] - '0';
+ *piState = *piState * 10 + buf[1] - '0';
+ *piState = *piState * 10 + buf[2] - '0';
+ if(*piState != iExpected)
+ ABORT_FINALIZE(RS_RET_SMTP_ERROR);
+ }
+ } while(bCont);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* create a timestamp suitable for use with the Date: SMTP body header
+ * rgerhards, 2008-04-08
+ */
+static void
+mkSMTPTimestamp(uchar *pszBuf, size_t lenBuf)
+{
+ time_t tCurr;
+ struct tm tmCurr;
+ static const char szDay[][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+ static const char szMonth[][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+
+ time(&tCurr);
+ gmtime_r(&tCurr, &tmCurr);
+ snprintf((char*)pszBuf, lenBuf, "Date: %s, %2d %s %4d %2d:%02d:%02d UT\r\n", szDay[tmCurr.tm_wday], tmCurr.tm_mday,
+ szMonth[tmCurr.tm_mon], 1900 + tmCurr.tm_year, tmCurr.tm_hour, tmCurr.tm_min, tmCurr.tm_sec);
+}
+
+
+/* send a message via SMTP
+ * rgerhards, 2008-04-04
+ */
+static rsRetVal
+sendSMTP(instanceData *pData, uchar *body, uchar *subject)
+{
+ DEFiRet;
+ int iState; /* SMTP state */
+ uchar szDateBuf[64];
+
+ assert(pData != NULL);
+
+ CHKiRet(serverConnect(pData));
+ CHKiRet(readResponse(pData, &iState, 220));
+
+ CHKiRet(Send(pData->md.smtp.sock, "HELO ", 5));
+ CHKiRet(Send(pData->md.smtp.sock, (char*)LocalHostName, strlen((char*)LocalHostName)));
+ CHKiRet(Send(pData->md.smtp.sock, "\r\n", sizeof("\r\n") - 1));
+ CHKiRet(readResponse(pData, &iState, 250));
+
+ CHKiRet(Send(pData->md.smtp.sock, "MAIL FROM: <", sizeof("MAIL FROM: <") - 1));
+ CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszFrom, strlen((char*)pData->md.smtp.pszFrom)));
+ CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1));
+ CHKiRet(readResponse(pData, &iState, 250));
+
+ CHKiRet(Send(pData->md.smtp.sock, "RCPT TO: <", sizeof("RCPT TO: <") - 1));
+ CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszTo, strlen((char*)pData->md.smtp.pszTo)));
+ CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1));
+ CHKiRet(readResponse(pData, &iState, 250));
+
+ CHKiRet(Send(pData->md.smtp.sock, "DATA\r\n", sizeof("DATA\r\n") - 1));
+ CHKiRet(readResponse(pData, &iState, 354));
+
+ /* now come the data part */
+ /* header */
+ mkSMTPTimestamp(szDateBuf, sizeof(szDateBuf));
+ CHKiRet(Send(pData->md.smtp.sock, (char*)szDateBuf, strlen((char*)szDateBuf)));
+
+ CHKiRet(Send(pData->md.smtp.sock, "From: <", sizeof("From: <") - 1));
+ CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszFrom, strlen((char*)pData->md.smtp.pszFrom)));
+ CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1));
+
+ CHKiRet(Send(pData->md.smtp.sock, "To: <", sizeof("To: <") - 1));
+ CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszTo, strlen((char*)pData->md.smtp.pszTo)));
+ CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1));
+
+ CHKiRet(Send(pData->md.smtp.sock, "Subject: ", sizeof("Subject: ") - 1));
+ CHKiRet(Send(pData->md.smtp.sock, (char*)subject, strlen((char*)subject)));
+ CHKiRet(Send(pData->md.smtp.sock, "\r\n", sizeof("\r\n") - 1));
+
+ CHKiRet(Send(pData->md.smtp.sock, "X-Mailer: rsyslog-immail\r\n", sizeof("x-mailer: rsyslog-immail\r\n") - 1));
+
+ CHKiRet(Send(pData->md.smtp.sock, "\r\n", sizeof("\r\n") - 1)); /* indicate end of header */
+
+ /* body */
+ if(pData->bEnableBody)
+ CHKiRet(bodySend(pData, (char*)body, strlen((char*) body)));
+
+ /* end of data, back to envelope transaction */
+ CHKiRet(Send(pData->md.smtp.sock, "\r\n.\r\n", sizeof("\r\n.\r\n") - 1));
+ CHKiRet(readResponse(pData, &iState, 250));
+
+ CHKiRet(Send(pData->md.smtp.sock, "QUIT\r\n", sizeof("QUIT\r\n") - 1));
+ CHKiRet(readResponse(pData, &iState, 221));
+
+ /* we are finished, a new connection is created for each request, so let's close it now */
+ CHKiRet(serverDisconnect(pData));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* in tryResume we check if we can connect to the server in question. If that is OK,
+ * we close the connection without doing any actual SMTP transaction. It will be
+ * reopened during the actual send process. This may not be the best way to do it if
+ * there is a problem inside the SMTP transaction. However, we can't find that out without
+ * actually initiating something, and that would be bad. The logic here helps us
+ * correctly recover from an unreachable/down mail server, which is probably the majority
+ * of problem cases. For SMTP transaction problems, we will do lots of retries, but if it
+ * is a temporary problem, it will be fixed anyhow. So I consider this implementation to
+ * be clean enough, especially as I think other approaches have other weaknesses.
+ * rgerhards, 2008-04-08
+ */
+BEGINtryResume
+CODESTARTtryResume
+ CHKiRet(serverConnect(pData));
+ CHKiRet(serverDisconnect(pData)); /* if we fail, we will never reach this line */
+finalize_it:
+ if(iRet == RS_RET_IO_ERROR)
+ iRet = RS_RET_SUSPENDED;
+ENDtryResume
+
+
+BEGINdoAction
+CODESTARTdoAction
+ dbgprintf(" Mail\n");
+
+ /* forward */
+ if(pData->bHaveSubject)
+ iRet = sendSMTP(pData, ppString[0], ppString[1]);
+ else
+ iRet = sendSMTP(pData, ppString[0], (uchar*)"message from rsyslog");
+
+ if(iRet != RS_RET_OK) {
+ /* error! */
+ dbgprintf("error sending mail, suspending\n");
+ iRet = RS_RET_SUSPENDED;
+ }
+ENDdoAction
+
+
+BEGINparseSelectorAct
+CODESTARTparseSelectorAct
+ if(!strncmp((char*) p, ":ommail:", sizeof(":ommail:") - 1)) {
+ p += sizeof(":ommail:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ } else {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ /* ok, if we reach this point, we have something for us */
+ if((iRet = createInstance(&pData)) != RS_RET_OK)
+ FINALIZE;
+
+ /* TODO: check strdup() result */
+
+ if(pszFrom == NULL) {
+ errmsg.LogError(NO_ERRCODE, "no sender address given - specify $ActionMailFrom");
+ ABORT_FINALIZE(RS_RET_MAIL_NO_FROM);
+ }
+ if(pszTo == NULL) {
+ errmsg.LogError(NO_ERRCODE, "no recipient address given - specify $ActionMailTo");
+ ABORT_FINALIZE(RS_RET_MAIL_NO_TO);
+ }
+
+ pData->md.smtp.pszFrom = (uchar*) strdup((char*)pszFrom);
+ pData->md.smtp.pszTo = (uchar*) strdup((char*)pszTo);
+
+ if(pszSubject == NULL) {
+ /* if no subject is configured, we need just one template string */
+ CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ } else {
+ CODE_STD_STRING_REQUESTparseSelectorAct(2)
+ pData->bHaveSubject = 1;
+ CHKiRet(OMSRsetEntry(*ppOMSR, 1, (uchar*)strdup((char*) pszSubject), OMSR_NO_RQD_TPL_OPTS));
+ }
+ if(pszSrv != NULL)
+ pData->md.smtp.pszSrv = (uchar*) strdup((char*)pszSrv);
+ if(pszSrvPort != NULL)
+ pData->md.smtp.pszSrvPort = (uchar*) strdup((char*)pszSrvPort);
+ pData->bEnableBody = bEnableBody;
+
+ /* process template */
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*) "RSYSLOG_FileFormat"));
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+/* Free string config variables and reset them to NULL (not necessarily the default!) */
+static rsRetVal freeConfigVariables(void)
+{
+ DEFiRet;
+
+ if(pszSrv != NULL) {
+ free(pszSrv);
+ pszSrv = NULL;
+ }
+ if(pszSrvPort != NULL) {
+ free(pszSrvPort);
+ pszSrvPort = NULL;
+ }
+ if(pszFrom != NULL) {
+ free(pszFrom);
+ pszFrom = NULL;
+ }
+ if(pszTo != NULL) {
+ free(pszTo);
+ pszTo = NULL;
+ }
+
+ RETiRet;
+}
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* cleanup our allocations */
+ freeConfigVariables();
+
+ /* release what we no longer need */
+ objRelease(errmsg, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+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;
+ bEnableBody = 1;
+ iRet = freeConfigVariables();
+ RETiRet;
+}
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ /* tell which objects we need */
+ CHKiRet(objUse(errmsg, CORE_COMPONENT));
+
+ CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailsmtpserver", 0, eCmdHdlrGetWord, NULL, &pszSrv, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailsmtpport", 0, eCmdHdlrGetWord, NULL, &pszSrvPort, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailfrom", 0, eCmdHdlrGetWord, NULL, &pszFrom, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailto", 0, eCmdHdlrGetWord, NULL, &pszTo, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailsubject", 0, eCmdHdlrGetWord, NULL, &pszSubject, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr( (uchar *)"actionmailenablebody", 0, eCmdHdlrBinary, NULL, &bEnableBody, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr( (uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
+
+/* vim:set ai:
+ */
diff --git a/plugins/omrelp/omrelp.c b/plugins/omrelp/omrelp.c
index 39d2581..0457168 100644
--- a/plugins/omrelp/omrelp.c
+++ b/plugins/omrelp/omrelp.c
@@ -53,7 +53,7 @@ DEFobjCurrIf(errmsg)
static relpEngine_t *pRelpEngine; /* our relp engine */
typedef struct _instanceData {
- char f_hname[MAXHOSTNAMELEN+1];
+ char *f_hname;
int compressionLevel; /* 0 - no compression, else level for zlib */
char *port;
int bInitialConnect; /* is this the initial connection request of our module? (0-no, 1-yes) */
@@ -98,6 +98,9 @@ CODESTARTfreeInstance
if(pData->pRelpClt != NULL)
relpEngineCltDestruct(pRelpEngine, &pData->pRelpClt);
+ if(pData->f_hname != NULL)
+ free(pData->f_hname);
+
ENDfreeInstance
@@ -284,10 +287,11 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1)
/* TODO: make this if go away! */
if(*p == ';') {
*p = '\0'; /* trick to obtain hostname (later)! */
- strcpy(pData->f_hname, (char*) q);
+ CHKmalloc(pData->f_hname = strdup((char*) q));
*p = ';';
- } else
- strcpy(pData->f_hname, (char*) q);
+ } else {
+ CHKmalloc(pData->f_hname = strdup((char*) q));
+ }
/* process template */
CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*) "RSYSLOG_ForwardFormat"));
diff --git a/queue.c b/queue.c
index 20ead4a..081f48b 100644
--- a/queue.c
+++ b/queue.c
@@ -39,6 +39,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h> /* required for HP UX */
+#include <time.h>
#include <errno.h>
#include "rsyslog.h"
@@ -56,6 +57,7 @@ DEFobjStaticHelpers
/* forward-definitions */
rsRetVal queueChkPersist(queue_t *pThis);
static rsRetVal queueSetEnqOnly(queue_t *pThis, int bEnqOnly, int bLockMutex);
+static rsRetVal queueRateLimiter(queue_t *pThis);
static int queueChkStopWrkrDA(queue_t *pThis);
static int queueIsIdleDA(queue_t *pThis);
static rsRetVal queueConsumerDA(queue_t *pThis, wti_t *pWti, int iCancelStateSave);
@@ -272,6 +274,8 @@ queueStartDA(queue_t *pThis)
CHKiRet(queueSettoActShutdown(pThis->pqDA, pThis->toActShutdown));
CHKiRet(queueSettoEnq(pThis->pqDA, pThis->toEnq));
CHKiRet(queueSetEnqOnly(pThis->pqDA, pThis->bDAEnqOnly, MUTEX_ALREADY_LOCKED));
+ CHKiRet(queueSetiDeqtWinFromHr(pThis->pqDA, pThis->iDeqtWinFromHr));
+ CHKiRet(queueSetiDeqtWinToHr(pThis->pqDA, pThis->iDeqtWinToHr));
CHKiRet(queueSetiHighWtrMrk(pThis->pqDA, 0));
CHKiRet(queueSetiDiscardMrk(pThis->pqDA, 0));
if(pThis->toQShutdown == 0) {
@@ -845,6 +849,8 @@ static rsRetVal qAddDisk(queue_t *pThis, void* pUsr)
pThis->tVars.disk.sizeOnDisk += nWriteCount;
+ /* The following line is a backport from 3.19.10 - fixes mem leak */
+ objDestruct(pUsr);
dbgoprint((obj_t*) pThis, "write wrote %lld octets to disk, queue disk size now %lld octets\n",
nWriteCount, pThis->tVars.disk.sizeOnDisk);
@@ -1268,6 +1274,7 @@ rsRetVal queueConstruct(queue_t **ppThis, queueType_t qType, int iWorkerThreads,
pThis->iMaxQueueSize = iMaxQueueSize;
pThis->pConsumer = pConsumer;
pThis->iNumWorkerThreads = iWorkerThreads;
+ pThis->iDeqtWinToHr = 25; /* disable time-windowed dequeuing by default */
pThis->pszFilePrefix = NULL;
pThis->qType = qType;
@@ -1412,12 +1419,10 @@ queueDequeueConsumable(queue_t *pThis, wti_t *pWti, int iCancelStateSave)
* on the nail [exact value]) -- rgerhards, 2008-03-14
*/
if(iQueueSize < pThis->iFullDlyMrk) {
-dbgoprint((obj_t*) pThis, "queue size %d below FullDlyMrk %d\n", iQueueSize, pThis->iFullDlyMrk);
pthread_cond_broadcast(&pThis->belowFullDlyWtrMrk);
}
if(iQueueSize < pThis->iLightDlyMrk) {
-dbgoprint((obj_t*) pThis, "queue size %d below LightDlyMrk %d\n", iQueueSize, pThis->iLightDlyMrk);
pthread_cond_broadcast(&pThis->belowLightDlyWtrMrk);
}
@@ -1451,6 +1456,104 @@ finalize_it:
}
+/* The rate limiter
+ *
+ * Here we may wait if a dequeue time window is defined or if we are
+ * rate-limited. TODO: If we do so, we should also look into the
+ * way new worker threads are spawned. Obviously, it doesn't make much
+ * sense to spawn additional worker threads when none of them can do any
+ * processing. However, it is deemed acceptable to allow this for an initial
+ * implementation of the timeframe/rate limiting feature.
+ * Please also note that these feature could also be implemented at the action
+ * level. However, that would limit them to be used together with actions. We have
+ * taken the broader approach, moving it right into the queue. This is even
+ * necessary if we want to prevent spawning of multiple unnecessary worker
+ * threads as described above. -- rgerhards, 2008-04-02
+ *
+ *
+ * time window: tCurr is current time; tFrom is start time, tTo is end time (in mil 24h format).
+ * We may have tFrom = 4, tTo = 10 --> run from 4 to 10 hrs. nice and happy
+ * we may also have tFrom= 22, tTo = 4 -> run from 10pm to 4am, which is actually two
+ * windows: 0-4; 22-23:59
+ * so when to run? Let's assume we have 3am
+ *
+ * if(tTo < tFrom) {
+ * if(tCurr < tTo [3 < 4] || tCurr > tFrom [3 > 22])
+ * do work
+ * else
+ * sleep for tFrom - tCurr "hours" [22 - 5 --> 17]
+ * } else {
+ * if(tCurr >= tFrom [3 >= 4] && tCurr < tTo [3 < 10])
+ * do work
+ * else
+ * sleep for tTo - tCurr "hours" [4 - 3 --> 1]
+ * }
+ *
+ * Bottom line: we need to check which type of window we have and need to adjust our
+ * logic accordingly. Of course, sleep calculations need to be done up to the minute,
+ * but you get the idea from the code above.
+ */
+static rsRetVal
+queueRateLimiter(queue_t *pThis)
+{
+ DEFiRet;
+ int iDelay;
+ int iHrCurr;
+ time_t tCurr;
+ struct tm m;
+
+ ISOBJ_TYPE_assert(pThis, queue);
+
+ dbgoprint((obj_t*) pThis, "entering rate limiter\n");
+
+ iDelay = 0;
+ if(pThis->iDeqtWinToHr != 25) { /* 25 means disabled */
+ /* time calls are expensive, so only do them when needed */
+ time(&tCurr);
+ localtime_r(&tCurr, &m);
+ iHrCurr = m.tm_hour;
+
+ if(pThis->iDeqtWinToHr < pThis->iDeqtWinFromHr) {
+ if(iHrCurr < pThis->iDeqtWinToHr || iHrCurr > pThis->iDeqtWinFromHr) {
+ ; /* do not delay */
+ } else {
+ iDelay = (pThis->iDeqtWinFromHr - iHrCurr) * 3600;
+ /* this time, we are already into the next hour, so we need
+ * to subtract our current minute and seconds.
+ */
+ iDelay -= m.tm_min * 60;
+ iDelay -= m.tm_sec;
+ }
+ } else {
+ if(iHrCurr >= pThis->iDeqtWinFromHr && iHrCurr < pThis->iDeqtWinToHr) {
+ ; /* do not delay */
+ } else {
+ if(iHrCurr < pThis->iDeqtWinFromHr) {
+ iDelay = (pThis->iDeqtWinFromHr - iHrCurr - 1) * 3600; /* -1 as we are already in the hour */
+ iDelay += (60 - m.tm_min) * 60;
+ iDelay += 60 - m.tm_sec;
+ } else {
+ iDelay = (24 - iHrCurr + pThis->iDeqtWinFromHr) * 3600;
+ /* this time, we are already into the next hour, so we need
+ * to subtract our current minute and seconds.
+ */
+ iDelay -= m.tm_min * 60;
+ iDelay -= m.tm_sec;
+ }
+ }
+ }
+ }
+
+ if(iDelay > 0) {
+ dbgoprint((obj_t*) pThis, "outside dequeue time window, delaying %d seconds\n", iDelay);
+ srSleep(iDelay, 0);
+ }
+
+ RETiRet;
+}
+
+
+
/* This is the queue consumer in the regular (non-DA) case. It is
* protected by the queue mutex, but MUST release it as soon as possible.
* rgerhards, 2008-01-21
@@ -1691,6 +1794,7 @@ rsRetVal queueStart(queue_t *pThis) /* this is the ConstructionFinalizer */
lenBuf = snprintf((char*)pszBuf, sizeof(pszBuf), "%s:Reg", obj.GetName((obj_t*) pThis));
CHKiRet(wtpConstruct (&pThis->pWtpReg));
CHKiRet(wtpSetDbgHdr (pThis->pWtpReg, pszBuf, lenBuf));
+ CHKiRet(wtpSetpfRateLimiter (pThis->pWtpReg, (rsRetVal (*)(void *pUsr)) queueRateLimiter));
CHKiRet(wtpSetpfChkStopWrkr (pThis->pWtpReg, (rsRetVal (*)(void *pUsr, int)) queueChkStopWrkrReg));
CHKiRet(wtpSetpfIsIdle (pThis->pWtpReg, (rsRetVal (*)(void *pUsr, int)) queueIsIdleReg));
CHKiRet(wtpSetpfDoWork (pThis->pWtpReg, (rsRetVal (*)(void *pUsr, void *pWti, int)) queueConsumerReg));
@@ -2152,6 +2256,8 @@ finalize_it:
/* some simple object access methods */
DEFpropSetMeth(queue, iPersistUpdCnt, int);
+DEFpropSetMeth(queue, iDeqtWinFromHr, int);
+DEFpropSetMeth(queue, iDeqtWinToHr, int);
DEFpropSetMeth(queue, toQShutdown, long);
DEFpropSetMeth(queue, toActShutdown, long);
DEFpropSetMeth(queue, toWrkShutdown, long);
@@ -2214,6 +2320,5 @@ BEGINObjClassInit(queue, 1, OBJ_IS_CORE_MODULE)
OBJSetMethodHandler(objMethod_SETPROPERTY, queueSetProperty);
ENDObjClassInit(queue)
-/*
- * vi:set ai:
+/* vi:set ai:
*/
diff --git a/queue.h b/queue.h
index e07d034..9e75b31 100644
--- a/queue.h
+++ b/queue.h
@@ -83,9 +83,20 @@ typedef struct queue_s {
int toActShutdown; /* timeout for long-running action shutdown in ms */
int toWrkShutdown; /* timeout for idle workers in ms, -1 means indefinite (0 is immediate) */
int toEnq; /* enqueue timeout */
- /* rate limiting settings (will be expanded */
+ /* rate limiting settings (will be expanded) */
int iDeqSlowdown; /* slow down dequeue by specified nbr of microseconds */
/* end rate limiting */
+ /* dequeue time window settings (may also be expanded) */
+ int iDeqtWinFromHr; /* begin of dequeue time window (hour only) */
+ int iDeqtWinToHr; /* end of dequeue time window (hour only), set to 25 to disable deq window! */
+ /* note that begin and end have specific semantics. It is a big difference if we have
+ * begin 4, end 22 or begin 22, end 4. In the later case, dequeuing will run from 10p,
+ * throughout the night and stop at 4 in the morning. In the first case, it will start
+ * at 4am, run throughout the day, and stop at 10 in the evening! So far, not logic is
+ * applied to detect user configuration errors (and tell me how should we detect what
+ * the user really wanted...). -- rgerhards, 2008-04-02
+ */
+ /* ane dequeue time window */
rsRetVal (*pConsumer)(void *,void*); /* user-supplied consumer function for dequeued messages */
/* calling interface for pConsumer: arg1 is the global user pointer from this structure, arg2 is the
* user pointer that was dequeued (actual sample: for actions, arg1 is the pAction and arg2 is pointer
@@ -174,6 +185,8 @@ rsRetVal queueConstruct(queue_t **ppThis, queueType_t qType, int iWorkerThreads,
int iMaxQueueSize, rsRetVal (*pConsumer)(void*,void*));
PROTOTYPEObjClassInit(queue);
PROTOTYPEpropSetMeth(queue, iPersistUpdCnt, int);
+PROTOTYPEpropSetMeth(queue, iDeqtWinFromHr, int);
+PROTOTYPEpropSetMeth(queue, iDeqtWinToHr, int);
PROTOTYPEpropSetMeth(queue, toQShutdown, long);
PROTOTYPEpropSetMeth(queue, toActShutdown, long);
PROTOTYPEpropSetMeth(queue, toWrkShutdown, long);
diff --git a/rsyslog.conf b/rsyslog.conf
index 2ff7d27..9448760 100644
--- a/rsyslog.conf
+++ b/rsyslog.conf
@@ -1,3 +1,6 @@
+# if you experience problems, check
+# http://www.rsyslog.com/troubleshoot for assistance
+
# rsyslog v3: load input modules
# If you do not load inputs, nothing happens!
# You may need to set the module load path if modules are not found.
@@ -41,7 +44,7 @@ local7.* /var/log/boot.log
#$ActionQueueMaxDiskSpace 1g # 1gb space limit (use as much as possible)
#$ActionQueueSaveOnShutdown on # save messages to disk on shutdown
#$ActionQueueType LinkedList # run asynchronously
-#$ActionResumeRetryCount -1 # infinety retries if host is down
+#$ActionResumeRetryCount -1 # infinite retries if host is down
# remote host is: name/ip:port, e.g. 192.168.0.1:514, port optional
#*.* @@remote-host
diff --git a/rsyslog.conf.5 b/rsyslog.conf.5
index 4fa98ef..122f3c8 100644
--- a/rsyslog.conf.5
+++ b/rsyslog.conf.5
@@ -17,7 +17,7 @@
.\" along with this program; if not, write to the Free Software
.\" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
.\"
-.TH RSYSLOG.CONF 5 "07 April 2008" "Version 3.15.1" "Linux System Administration"
+.TH RSYSLOG.CONF 5 "11 July 2008" "Version 3.18.0" "Linux System Administration"
.SH NAME
rsyslog.conf \- rsyslogd(8) configuration file
.SH DESCRIPTION
@@ -28,8 +28,8 @@ file is the main configuration file for the
which logs system messages on *nix systems. This file specifies rules
for logging. For special features see the
.BR rsyslogd (8)
-manpage. Ryslog.conf is backward-compatible with sysklogd's syslog.conf file. So if you migrate
-from syklogd you can rename it and it should work.
+manpage. Rsyslog.conf is backward-compatible with sysklogd's syslog.conf file. So if you migrate
+from sysklogd you can rename it and it should work.
.B Note that this version of rsyslog ships with extensive documentation in html format.
This is provided in the ./doc subdirectory and probably
@@ -55,7 +55,7 @@ Output module for GSS-enabled syslog
.I ommysql
Output module for MySQL
.TP
-.I omprelp
+.I omrelp
Output module for the reliable RELP protocol (prevents message loss).
For details, see below at imrelp and the html documentation.
It can be used like this:
@@ -69,7 +69,7 @@ Output module for PostgreSQL
.TP
.I omlibdbi
Generic database output module (Firebird/Interbase, MS SQL, Sybase,
-SQLLite, Ingres, Oracle, mSQL)
+SQLite, Ingres, Oracle, mSQL)
.TP
.I imfile
Input module for text files
@@ -208,7 +208,7 @@ string ":omrelp:" in front of the hostname.
.sp
In the example above, messages are forwarded via UDP to the machine 192.168.0.1, the destination
port defaults to 514. Due to the nature of UDP, you will probably lose some messages in transit.
-If you expect high traffic volume, you can expect to lose a quite noticable number of messages
+If you expect high traffic volume, you can expect to lose a quite noticeable number of messages
(the higher the traffic, the more likely and severe is message loss).
.B If you would like to prevent message loss, use RELP:
diff --git a/rsyslog.h b/rsyslog.h
index a80d43d..c73c659 100644
--- a/rsyslog.h
+++ b/rsyslog.h
@@ -167,6 +167,11 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
RS_RET_MODULE_LOAD_ERR_DLOPEN = -2066, /**< module could not be loaded - problem in dlopen() */
RS_RET_MODULE_LOAD_ERR_NO_INIT = -2067, /**< module could not be loaded - init() missing */
RS_RET_MODULE_LOAD_ERR_INIT_FAILED = -2068, /**< module could not be loaded - init() failed */
+ RS_RET_NO_SOCKET = -2069, /**< socket could not be obtained or was not provided */
+ RS_RET_SMTP_ERROR = -2070, /**< error during SMTP transation */
+ RS_RET_MAIL_NO_TO = -2071, /**< recipient for mail destination is missing */
+ RS_RET_MAIL_NO_FROM = -2072, /**< sender for mail destination is missing */
+ RS_RET_INVALID_PRI = -2073, /**< PRI value is invalid */
/* RainerScript error messages (range 1000.. 1999) */
RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */
diff --git a/rsyslogd.8 b/rsyslogd.8
index 0125d58..91f2016 100644
--- a/rsyslogd.8
+++ b/rsyslogd.8
@@ -1,7 +1,7 @@
.\" Copyright 2004-2008 Rainer Gerhards and Adiscon for the rsyslog modifications
.\" May be distributed under the GNU General Public License
.\"
-.TH RSYSLOGD 8 "02 April 2008" "Version 3.14.0" "Linux System Administration"
+.TH RSYSLOGD 8 "11 July 2008" "Version 3.18.0" "Linux System Administration"
.SH NAME
rsyslogd \- reliable and extended syslogd
.SH SYNOPSIS
@@ -266,7 +266,7 @@ Disabling inet domain sockets will limit risk to the local machine.
If remote logging is enabled, messages can easily be spoofed and replayed.
As the messages are transmitted in clear-text, an attacker might use
the information obtained from the packets for malicious things. Also, an
-attacker might reply recorded messages or spoof a sender's IP address,
+attacker might replay recorded messages or spoof a sender's IP address,
which could lead to a wrong perception of system activity. These can
be prevented by using GSS-API authentication and encryption. Be sure
to think about syslog network security before enabling it.
@@ -310,7 +310,7 @@ following options possible (all are case insensitive):
.IP LogFuncFlow
Print out the logical flow of functions (entering and exiting them)
.IP FileTrace
-Ppecifies which files to trace LogFuncFlow. If not set (the
+Specifies which files to trace LogFuncFlow. If not set (the
default), a LogFuncFlow trace is provided for all files. Set to
limit it to the files specified.FileTrace may be specified multiple
times, one file each (e.g. export RSYSLOG_DEBUG="LogFuncFlow
diff --git a/stringbuf.h b/stringbuf.h
index 0d61769..e44e86e 100644
--- a/stringbuf.h
+++ b/stringbuf.h
@@ -121,6 +121,7 @@ void rsCStrSetAllocIncrement(cstr_t *pThis, int iNewIncrement);
rsRetVal rsCStrAppendInt(cstr_t *pThis, long i);
+rsRetVal strExit(void); /* TODO: remove once we have a real object interface! */
uchar* rsCStrGetSzStr(cstr_t *pThis);
uchar* rsCStrGetSzStrNoNULL(cstr_t *pThis);
rsRetVal rsCStrSetSzStr(cstr_t *pThis, uchar *pszNew);
diff --git a/syslogd.c b/syslogd.c
index 26dd35c..35e91af 100644
--- a/syslogd.c
+++ b/syslogd.c
@@ -216,7 +216,7 @@ static rsRetVal GlobalClassExit(void);
#if defined(SYSLOGD_PIDNAME)
# undef _PATH_LOGPID
# if defined(FSSTND)
-# ifdef BSD
+# ifdef OS_BSD
# define _PATH_VARRUN "/var/run/"
# endif
# if defined(__sun) || defined(__hpux)
@@ -301,10 +301,12 @@ static uchar cCCEscapeChar = '\\';/* character to be used to start an escape seq
static int bEscapeCCOnRcv = 1; /* escape control characters on reception: 0 - no, 1 - yes */
int bReduceRepeatMsgs; /* reduce repeated message - 0 - no, 1 - yes */
int bActExecWhenPrevSusp; /* execute action only when previous one was suspended? */
+int iActExecOnceInterval = 0; /* execute action once every nn seconds */
uchar *pszWorkDir = NULL;/* name of rsyslog's spool directory (without trailing slash) */
+uchar *glblModPath = NULL; /* module load path - only used during initial init, only settable via -M command line option */
/* end global config file state variables */
-char LocalHostName[MAXHOSTNAMELEN+1];/* our hostname - read-only after startup */
+uchar *LocalHostName;/* our hostname - read-only after startup */
char *LocalDomain; /* our local domain name - read-only after startup */
int MarkInterval = 20 * 60; /* interval between marks in seconds - read-only after startup */
int family = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both), set via cmdline */
@@ -338,8 +340,10 @@ static int iMainMsgQtoEnq = 2000; /* timeout for queue enque */
static int iMainMsgQtoWrkShutdown = 60000; /* timeout for worker thread shutdown */
static int iMainMsgQWrkMinMsgs = 100; /* minimum messages per worker needed to start a new one */
static int iMainMsgQDeqSlowdown = 0; /* dequeue slowdown (simple rate limiting) */
-static int bMainMsgQSaveOnShutdown = 1; /* save queue on shutdown (when DA enabled)? */
static int64 iMainMsgQueMaxDiskSpace = 0; /* max disk space allocated 0 ==> unlimited */
+static int bMainMsgQSaveOnShutdown = 1; /* save queue on shutdown (when DA enabled)? */
+static int iMainMsgQueueDeqtWinFromHr = 0; /* hour begin of time frame when queue is to be dequeued */
+static int iMainMsgQueueDeqtWinToHr = 25; /* hour begin of time frame when queue is to be dequeued */
/* support for simple textual representation of FIOP names
@@ -376,6 +380,7 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
{
cCCEscapeChar = '#';
bActExecWhenPrevSusp = 0;
+ iActExecOnceInterval = 0;
bDebugPrintTemplateList = 1;
bDebugPrintCfSysLineHandlerList = 1;
bDebugPrintModuleList = 1;
@@ -419,11 +424,11 @@ int option_DisallowWarning = 1; /* complain if message from disallowed sender is
/* hardcoded standard templates (used for defaults) */
static uchar template_SyslogProtocol23Format[] = "\"<%PRI%>1 %TIMESTAMP:::date-rfc3339% %HOSTNAME% %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg%\n\"";
-static uchar template_TraditionalFileFormat[] = "\"%TIMESTAMP% %HOSTNAME% %syslogtag%%msg:::drop-last-lf%\n\"";
-static uchar template_FileFormat[] = "\"%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::drop-last-lf%\n\"";
+static uchar template_TraditionalFileFormat[] = "\"%TIMESTAMP% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n\"";
+static uchar template_FileFormat[] = "\"%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n\"";
static uchar template_WallFmt[] = "\"\r\n\7Message from syslogd@%HOSTNAME% at %timegenerated% ...\r\n %syslogtag%%msg%\n\r\"";
-static uchar template_ForwardFormat[] = "\"<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag:1:32%%msg%\"";
-static uchar template_TraditionalForwardFormat[] = "\"<%PRI%>%TIMESTAMP% %HOSTNAME% %syslogtag:1:32%%msg%\"";
+static uchar template_ForwardFormat[] = "\"<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%\"";
+static uchar template_TraditionalForwardFormat[] = "\"<%PRI%>%TIMESTAMP% %HOSTNAME% %syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%\"";
static uchar template_StdUsrMsgFmt[] = "\" %syslogtag%%msg%\n\r\"";
static uchar template_StdDBFmt[] = "\"insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%', %syslogpriority%, '%timereported:::date-mysql%', '%timegenerated:::date-mysql%', %iut%, '%syslogtag%')\",SQL";
static uchar template_StdPgSQLFmt[] = "\"insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%', %syslogpriority%, '%timereported:::date-pgsql%', '%timegenerated:::date-pgsql%', %iut%, '%syslogtag%')\",STDSQL";
@@ -892,8 +897,8 @@ logmsgInternal(int pri, char *msg, int flags)
CHKiRet(msgConstruct(&pMsg));
MsgSetUxTradMsg(pMsg, msg);
MsgSetRawMsg(pMsg, msg);
- MsgSetHOSTNAME(pMsg, LocalHostName);
- MsgSetRcvFrom(pMsg, LocalHostName);
+ MsgSetHOSTNAME(pMsg, (char*)LocalHostName);
+ MsgSetRcvFrom(pMsg, (char*)LocalHostName);
MsgSetTAG(pMsg, "rsyslogd:");
pMsg->iFacility = LOG_FAC(pri);
pMsg->iSeverity = LOG_PRI(pri);
@@ -1385,11 +1390,18 @@ static int parseLegacySyslogMsg(msg_t *pMsg, int flags)
/* Check to see if msg contains a timestamp. We stary trying with a
* high-precision one...
*/
- if(datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse) == TRUE)
+ if(datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse) == TRUE) {
/* we are done - parse pointer is moved by ParseTIMESTAMP3339 */;
- else if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), p2parse) == TRUE)
+ } else if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), p2parse) == TRUE) {
p2parse += 16;
- else {
+ } else if(*p2parse == ' ') { /* try to see if it is slighly malformed - HP procurve seems to do that sometimes */
+ if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), p2parse+1) == TRUE) {
+ /* indeed, we got it! */
+ p2parse += 17;
+ } else {
+ flags |= ADDDATE;
+ }
+ } else {
flags |= ADDDATE;
}
@@ -1560,8 +1572,7 @@ submitMsg(msg_t *pMsg)
}
-/*
- * Log a message to the appropriate log files, users, etc. based on
+/* Log a message to the appropriate log files, users, etc. based on
* the priority.
* rgerhards 2004-11-08: actually, this also decodes all but the PRI part.
* rgerhards 2004-11-09: ... but only, if syslogd could properly be initialized
@@ -1858,6 +1869,8 @@ freeAllDynMemForTermination(void)
free(pszMainMsgQFName);
if(pModDir != NULL)
free(pModDir);
+ if(LocalHostName != NULL)
+ free(LocalHostName);
}
@@ -2197,8 +2210,7 @@ init(void)
pDfltProgNameCmp = NULL;
eDfltHostnameCmpMode = HN_NO_COMP;
- dbgprintf("rsyslog %s.\n", VERSION);
- dbgprintf("Called init.\n");
+ dbgprintf("rsyslog %s - called init()\n", VERSION);
/* delete the message queue, which also flushes all messages left over */
if(pMsgQueue != NULL) {
@@ -2220,12 +2232,12 @@ init(void)
tplDeleteNew();
/* re-setting values to defaults (where applicable) */
- /* TODO: once we have loadable modules, we must re-visit this code. The reason is
+ /* once we have loadable modules, we must re-visit this code. The reason is
* that config variables are not re-set, because the module is not yet loaded. On
* the other hand, that doesn't matter, because the module got unloaded and is then
- * re-loaded, so the variables should be re-set via that way. In any case, we should
- * think about the whole situation when we implement loadable plugins.
- * rgerhards, 2007-07-31
+ * re-loaded, so the variables should be re-set via that way. And this is exactly how
+ * it works. Loadable module's variables are initialized on load, the rest here.
+ * rgerhards, 2008-04-28
*/
conf.cfsysline((uchar*)"ResetConfigVariables");
@@ -2321,6 +2333,8 @@ init(void)
setQPROP(queueSetiMinMsgsPerWrkr, "$MainMsgQueueWorkerThreadMinimumMessages", iMainMsgQWrkMinMsgs);
setQPROP(queueSetbSaveOnShutdown, "$MainMsgQueueSaveOnShutdown", bMainMsgQSaveOnShutdown);
setQPROP(queueSetiDeqSlowdown, "$MainMsgQueueDequeueSlowdown", iMainMsgQDeqSlowdown);
+ setQPROP(queueSetiDeqtWinFromHr, "$MainMsgQueueDequeueTimeBegin", iMainMsgQueueDeqtWinFromHr);
+ setQPROP(queueSetiDeqtWinToHr, "$MainMsgQueueDequeueTimeEnd", iMainMsgQueueDeqtWinToHr);
# undef setQPROP
# undef setQPROPstr
@@ -2685,8 +2699,11 @@ static rsRetVal loadBuildInModules(void)
CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuemaxfilesize", 0, eCmdHdlrSize, NULL, &iMainMsgQueMaxFileSize, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuemaxdiskspace", 0, eCmdHdlrSize, NULL, &iMainMsgQueMaxDiskSpace, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesaveonshutdown", 0, eCmdHdlrBinary, NULL, &bMainMsgQSaveOnShutdown, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeuetimebegin", 0, eCmdHdlrInt, NULL, &iMainMsgQueueDeqtWinFromHr, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeuetimeend", 0, eCmdHdlrInt, NULL, &iMainMsgQueueDeqtWinToHr, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"repeatedmsgreduction", 0, eCmdHdlrBinary, NULL, &bReduceRepeatMsgs, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"actionexeconlywhenpreviousissuspended", 0, eCmdHdlrBinary, NULL, &bActExecWhenPrevSusp, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionexeconlyonceeveryinterval", 0, eCmdHdlrInt, NULL, &iActExecOnceInterval, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeinterval", 0, eCmdHdlrInt, setActionResumeInterval, NULL, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"controlcharacterescapeprefix", 0, eCmdHdlrGetChar, NULL, &cCCEscapeChar, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactersonreceive", 0, eCmdHdlrBinary, NULL, &bEscapeCCOnRcv, NULL));
@@ -2764,21 +2781,6 @@ static void mainThread()
BEGINfunc
uchar *pTmp;
-#if 0 // code moved back to main()
- /* doing some core initializations */
- if((iRet = modInitIminternal()) != RS_RET_OK) {
- fprintf(stderr, "fatal error: could not initialize errbuf object (error code %d).\n",
- iRet);
- exit(1); /* "good" exit, leaving at init for fatal error */
- }
-
- if((iRet = loadBuildInModules()) != RS_RET_OK) {
- fprintf(stderr, "fatal error: could not activate built-in modules. Error code %d.\n",
- iRet);
- exit(1); /* "good" exit, leaving at init for fatal error */
- }
-#endif
-
/* Note: signals MUST be processed by the thread this code is running in. The reason
* is that we need to interrupt the select() system call. -- rgerhards, 2007-10-17
*/
@@ -2803,7 +2805,6 @@ static void mainThread()
pTmp = template_StdPgSQLFmt;
tplLastStaticInit(tplAddLine(" StdPgSQLFmt", &pTmp));
- dbgprintf("Starting.\n");
init();
if(Debug) {
dbgprintf("Debugging enabled, SIGUSR1 to turn off debugging.\n");
@@ -2820,6 +2821,7 @@ static void mainThread()
* do the init() and then restart things.
* rgerhards, 2005-10-24
*/
+ dbgprintf("initialization completed, transitioning to regular run mode\n");
mainloop();
ENDfunc
@@ -2971,6 +2973,72 @@ GlobalClassExit(void)
}
+/* some support for command line option parsing. Any non-trivial options must be
+ * buffered until the complete command line has been parsed. This is necessary to
+ * prevent dependencies between the options. That, in turn, means we need to have
+ * something that is capable of buffering options and there values. The follwing
+ * functions handle that.
+ * rgerhards, 2008-04-04
+ */
+typedef struct bufOpt {
+ struct bufOpt *pNext;
+ char optchar;
+ char *arg;
+} bufOpt_t;
+static bufOpt_t *bufOptRoot = NULL;
+static bufOpt_t *bufOptLast = NULL;
+
+/* add option buffer */
+static rsRetVal
+bufOptAdd(char opt, char *arg)
+{
+ DEFiRet;
+ bufOpt_t *pBuf;
+
+ if((pBuf = malloc(sizeof(bufOpt_t))) == NULL)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+
+ pBuf->optchar = opt;
+ pBuf->arg = arg;
+ pBuf->pNext = NULL;
+
+ if(bufOptLast == NULL) {
+ bufOptRoot = pBuf; /* then there is also no root! */
+ } else {
+ bufOptLast->pNext = pBuf;
+ }
+ bufOptLast = pBuf;
+
+finalize_it:
+ RETiRet;
+}
+
+
+
+/* remove option buffer from top of list, return values and destruct buffer itself.
+ * returns RS_RET_END_OF_LINKEDLIST when no more options are present.
+ * (we use int *opt instead of char *opt to keep consistent with getopt())
+ */
+static rsRetVal
+bufOptRemove(int *opt, char **arg)
+{
+ DEFiRet;
+ bufOpt_t *pBuf;
+
+ if(bufOptRoot == NULL)
+ ABORT_FINALIZE(RS_RET_END_OF_LINKEDLIST);
+ pBuf = bufOptRoot;
+
+ *opt = pBuf->optchar;
+ *arg = pBuf->arg;
+
+ bufOptRoot = pBuf->pNext;
+ free(pBuf);
+
+finalize_it:
+ RETiRet;
+}
+
/* This is the main entry point into rsyslogd. Over time, we should try to
* modularize it a bit more...
@@ -2990,15 +3058,125 @@ int realMain(int argc, char **argv)
int bIsFirstOption = 1;
int bEOptionWasGiven = 0;
int bImUxSockLoaded = 0; /* already generated a $ModLoad imuxsock? */
+ char *arg; /* for command line option processing */
uchar legacyConfLine[80];
- gethostname(LocalHostName, sizeof(LocalHostName));
- if ( (p = strchr(LocalHostName, '.')) ) {
+ /* first, parse the command line options. We do not carry out any actual work, just
+ * see what we should do. This relieves us from certain anomalies and we can process
+ * the parameters down below in the correct order. For example, we must know the
+ * value of -M before we can do the init, but at the same time we need to have
+ * the base classes init before we can process most of the options. Now, with the
+ * split of functionality, this is no longer a problem. Thanks to varmofekoj for
+ * suggesting this algo.
+ * Note: where we just need to set some flags and can do so without knowledge
+ * of other options, we do this during the inital option processing. With later
+ * versions (if a dependency on -c option is introduced), we must move that code
+ * to other places, but I think it is quite appropriate and saves code to do this
+ * only when actually neeeded.
+ * rgerhards, 2008-04-04
+ */
+ while ((ch = getopt(argc, argv, "46aAc:def:g:hi:l:m:M:nopqQr::s:t:u:vwx")) != EOF) {
+ switch((char)ch) {
+ case '4':
+ case '6':
+ case 'A':
+ case 'a':
+ case 'f': /* configuration file */
+ case 'h':
+ case 'i': /* pid file name */
+ case 'l':
+ case 'm': /* mark interval */
+ case 'n': /* don't fork */
+ case 'o':
+ case 'p':
+ case 'q': /* add hostname if DNS resolving has failed */
+ case 'Q': /* dont resolve hostnames in ACL to IPs */
+ case 's':
+ case 'u': /* misc user settings */
+ case 'w': /* disable disallowed host warnings */
+ case 'x': /* disable dns for remote messages */
+ CHKiRet(bufOptAdd(ch, optarg));
+ break;
+ case 'c': /* compatibility mode */
+ if(!bIsFirstOption) {
+ fprintf(stderr, "-c option MUST be specified as the first option - aborting...\n");
+ usage();
+ exit(1);
+ }
+ iCompatibilityMode = atoi(optarg);
+ break;
+ case 'd': /* debug - must be handled now, so that debug is active during init! */
+ Debug = 1;
+ break;
+ case 'e': /* log every message (no repeat message supression) */
+ fprintf(stderr, "note: -e option is no longer supported, every message is now logged by default\n");
+ bEOptionWasGiven = 1;
+ break;
+ case 'g': /* enable tcp gssapi logging */
+#if defined(SYSLOG_INET) && defined(USE_GSSAPI)
+ CHKiRet(bufOptAdd('g', optarg));
+#else
+ fprintf(stderr, "rsyslogd: -g not valid - not compiled with gssapi support");
+#endif
+ break;
+ case 'M': /* default module load path -- this MUST be carried out immediately! */
+ glblModPath = (uchar*) optarg;
+ break;
+ case 'r': /* accept remote messages */
+#ifdef SYSLOG_INET
+ CHKiRet(bufOptAdd(ch, optarg));
+#else
+ fprintf(stderr, "rsyslogd: -r not valid - not compiled with network support\n");
+#endif
+ break;
+ case 't': /* enable tcp logging */
+#ifdef SYSLOG_INET
+ CHKiRet(bufOptAdd(ch, optarg));
+#else
+ fprintf(stderr, "rsyslogd: -t not valid - not compiled with network support\n");
+#endif
+ break;
+ case 'v': /* MUST be carried out immediately! */
+ printVersion();
+ exit(0); /* exit for -v option - so this is a "good one" */
+ case '?':
+ default:
+ usage();
+ }
+ bIsFirstOption = 0; /* we already saw an option character */
+ }
+
+ if ((argc -= optind))
+ usage();
+
+ dbgprintf("rsyslogd %s startup, compatibility mode %d, module path '%s'\n",
+ VERSION, iCompatibilityMode, glblModPath == NULL ? "" : (char*)glblModPath);
+
+ /* we are done with the initial option parsing and processing. Now we init the system. */
+
+ ppid = getpid();
+
+ if(chdir ("/") != 0)
+ fprintf(stderr, "Can not do 'cd /' - still trying to run\n");
+
+ CHKiRet_Hdlr(InitGlobalClasses()) {
+ fprintf(stderr, "rsyslogd initializiation failed - global classes could not be initialized.\n"
+ "Did you do a \"make install\"?\n"
+ "Suggested action: run rsyslogd with -d -n options to see what exactly "
+ "fails.\n");
+ FINALIZE;
+ }
+
+ /* doing some core initializations */
+
+ /* get our host and domain names - we need to do this early as we may emit
+ * error log messages, which need the correct hostname. -- rgerhards, 2008-04-04
+ */
+ net.getLocalHostname(&LocalHostName);
+ if((p = strchr((char*)LocalHostName, '.'))) {
*p++ = '\0';
LocalDomain = p;
- }
- else
- {
+ } else {
LocalDomain = "";
/* It's not clearly defined whether gethostname()
@@ -3014,11 +3192,12 @@ int realMain(int argc, char **argv)
/* TODO: gethostbyname() is not thread-safe, but replacing it is
* not urgent as we do not run on multiple threads here. rgerhards, 2007-09-25
*/
- hent = gethostbyname(LocalHostName);
+ hent = gethostbyname((char*)LocalHostName);
if(hent) {
- snprintf(LocalHostName, sizeof(LocalHostName), "%s", hent->h_name);
+ free(LocalHostName);
+ CHKmalloc(LocalHostName = (uchar*)strdup(hent->h_name));
- if ( (p = strchr(LocalHostName, '.')) )
+ if((p = strchr((char*)LocalHostName, '.')))
{
*p++ = '\0';
LocalDomain = p;
@@ -3026,21 +3205,11 @@ int realMain(int argc, char **argv)
}
}
- /* Convert to lower case to recognize the correct domain laterly
- */
- for (p = (char *)LocalDomain; *p ; p++)
- if (isupper((int) *p))
- *p = (char)tolower((int)*p);
+ /* Convert to lower case to recognize the correct domain laterly */
+ for (p = (char *)LocalDomain ; *p ; p++)
+ *p = (char)tolower((int)*p);
- CHKiRet_Hdlr(InitGlobalClasses()) {
- fprintf(stderr, "rsyslogd initializiation failed - global classes could not be initialized.\n"
- "Did you do a \"make install\"?\n"
- "Suggested action: run rsyslogd with -d -n options to see what exactly "
- "fails.\n");
- FINALIZE;
- }
-
- /* doing some core initializations */
+ /* initialize the objects */
if((iRet = modInitIminternal()) != RS_RET_OK) {
fprintf(stderr, "fatal error: could not initialize errbuf object (error code %d).\n",
iRet);
@@ -3053,14 +3222,10 @@ int realMain(int argc, char **argv)
exit(1); /* "good" exit, leaving at init for fatal error */
}
- ppid = getpid();
-
- if(chdir ("/") != 0)
- fprintf(stderr, "Can not do 'cd /' - still trying to run\n");
-
- /* END core initializations */
+ /* END core initializations - we now come back to carrying out command line options*/
- while ((ch = getopt(argc, argv, "46aAc:def:g:hi:l:m:M:nopqQr::s:t:u:vwx")) != EOF) {
+ while((iRet = bufOptRemove(&ch, &arg)) == RS_RET_OK) {
+ dbgprintf("deque option %c, optarg '%s'\n", ch, arg);
switch((char)ch) {
case '4':
family = PF_INET;
@@ -3077,39 +3242,20 @@ int realMain(int argc, char **argv)
legacyOptsEnq((uchar *) "ModLoad imuxsock");
bImUxSockLoaded = 1;
}
- snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "addunixlistensocket %s", optarg);
+ snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "addunixlistensocket %s", arg);
legacyOptsEnq(legacyConfLine);
} else {
fprintf(stderr, "error -a is no longer supported, use module imuxsock instead");
}
break;
- case 'c': /* compatibility mode */
- if(!bIsFirstOption) {
- fprintf(stderr, "-c option MUST be specified as the first option - aborting...\n");
- usage();
- exit(1);
- }
- iCompatibilityMode = atoi(optarg);
- break;
- case 'd': /* debug */
- Debug = 1;
- break;
- case 'e': /* log every message (no repeat message supression) */
- fprintf(stderr, "note: -e option is no longer supported, every message is now logged by default\n");
- bEOptionWasGiven = 1;
- break;
case 'f': /* configuration file */
- ConfFile = (uchar*) optarg;
+ ConfFile = (uchar*) arg;
break;
case 'g': /* enable tcp gssapi logging */
-#if defined(SYSLOG_INET) && defined(USE_GSSAPI)
if(iCompatibilityMode < 3) {
- legacyOptsParseTCP(ch, optarg);
+ legacyOptsParseTCP(ch, arg);
} else
fprintf(stderr, "-g option only supported in compatibility modes 0 to 2 - ignored\n");
-#else
- fprintf(stderr, "rsyslogd: -g not valid - not compiled with gssapi support");
-#endif
break;
case 'h':
if(iCompatibilityMode < 3) {
@@ -3119,25 +3265,22 @@ int realMain(int argc, char **argv)
}
break;
case 'i': /* pid file name */
- PidFile = optarg;
+ PidFile = arg;
break;
case 'l':
if (LocalHosts) {
fprintf (stderr, "rsyslogd: Only one -l argument allowed, the first one is taken.\n");
} else {
- LocalHosts = crunch_list(optarg);
+ LocalHosts = crunch_list(arg);
}
break;
case 'm': /* mark interval */
if(iCompatibilityMode < 3) {
- MarkInterval = atoi(optarg) * 60;
+ MarkInterval = atoi(arg) * 60;
} else
fprintf(stderr,
"-m option only supported in compatibility modes 0 to 2 - ignored\n");
break;
- case 'M': /* default module load path */
- module.SetModDir((uchar*)optarg);
- break;
case 'n': /* don't fork */
NoFork = 1;
break;
@@ -3158,7 +3301,7 @@ int realMain(int argc, char **argv)
legacyOptsEnq((uchar *) "ModLoad imuxsock");
bImUxSockLoaded = 1;
}
- snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "SystemLogSocketName %s", optarg);
+ snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "SystemLogSocketName %s", arg);
legacyOptsEnq(legacyConfLine);
} else {
fprintf(stderr, "error -p is no longer supported, use module imuxsock instead");
@@ -3170,43 +3313,31 @@ int realMain(int argc, char **argv)
*net.pACLDontResolve = 1;
break;
case 'r': /* accept remote messages */
-#ifdef SYSLOG_INET
if(iCompatibilityMode < 3) {
legacyOptsEnq((uchar *) "ModLoad imudp");
- snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "UDPServerRun %s", optarg);
+ snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "UDPServerRun %s", arg);
legacyOptsEnq(legacyConfLine);
} else
- fprintf(stderr,
- "-r option only supported in compatibility modes 0 to 2 - ignored\n");
-#else
- fprintf(stderr, "rsyslogd: -r not valid - not compiled with network support\n");
-#endif
+ fprintf(stderr, "-r option only supported in compatibility modes 0 to 2 - ignored\n");
break;
case 's':
if (StripDomains) {
fprintf (stderr, "rsyslogd: Only one -s argument allowed, the first one is taken.\n");
} else {
- StripDomains = crunch_list(optarg);
+ StripDomains = crunch_list(arg);
}
break;
case 't': /* enable tcp logging */
-#ifdef SYSLOG_INET
if(iCompatibilityMode < 3) {
- legacyOptsParseTCP(ch, optarg);
+ legacyOptsParseTCP(ch, arg);
} else
fprintf(stderr, "-t option only supported in compatibility modes 0 to 2 - ignored\n");
-#else
- fprintf(stderr, "rsyslogd: -t not valid - not compiled with network support\n");
-#endif
break;
case 'u': /* misc user settings */
- if(atoi(optarg) == 1)
+ if(atoi(arg) == 1)
bParseHOSTNAMEandTAG = 0;
break;
- case 'v':
- printVersion();
- exit(0); /* exit for -v option - so this is a "good one" */
- case 'w': /* disable disallowed host warnigs */
+ case 'w': /* disable disallowed host warnings */
option_DisallowWarning = 0;
break;
case 'x': /* disable dns for remote messages */
@@ -3216,15 +3347,12 @@ int realMain(int argc, char **argv)
default:
usage();
}
- bIsFirstOption = 0; /* we already saw an option character */
}
- if ((argc -= optind))
- usage();
+ if(iRet != RS_RET_END_OF_LINKEDLIST)
+ FINALIZE;
- /* TODO: this should go away at a reasonable stage of v3 development.
- * rgerhards, 2007-12-19
- */
+ /* process compatibility mode settings */
if(iCompatibilityMode < 3) {
errmsg.LogError(NO_ERRCODE, "WARNING: rsyslogd is running in compatibility mode. Automatically "
"generated config directives may interfer with your rsyslog.conf settings. "
@@ -3250,7 +3378,7 @@ int realMain(int argc, char **argv)
checkPermissions();
thrdInit();
- if ( !(Debug || NoFork) )
+ if( !(Debug || NoFork) )
{
dbgprintf("Checking pidfile.\n");
if (!check_pid(PidFile))
@@ -3289,8 +3417,6 @@ int realMain(int argc, char **argv)
else
debugging_on = 1;
- dbgprintf("Compatibility Mode: %d\n", iCompatibilityMode);
-
/* tuck my process id away */
dbgprintf("Writing pidfile %s.\n", PidFile);
if (!check_pid(PidFile))
diff --git a/syslogd.h b/syslogd.h
index 4eefd32..46de8d2 100644
--- a/syslogd.h
+++ b/syslogd.h
@@ -134,7 +134,7 @@ rsRetVal logmsgInternal(int pri, char *msg, int flags);
void logmsg(msg_t *pMsg, int flags);
rsRetVal submitMsg(msg_t *pMsg);
extern int glblHadMemShortage; /* indicates if we had memory shortage some time during the run */
-extern char LocalHostName[];
+extern uchar *LocalHostName;
extern int family;
extern int NoHops;
extern int send_to_all;
@@ -149,6 +149,7 @@ extern char ctty[];
extern int MarkInterval;
extern int bReduceRepeatMsgs;
extern int bActExecWhenPrevSusp;
+extern int iActExecOnceInterval;
/* Intervals at which we flush out "message repeated" messages,
* in seconds after previous message is logged. After each flush,
diff --git a/tcpsrv.c b/tcpsrv.c
index adbe26e..955fb9b 100644
--- a/tcpsrv.c
+++ b/tcpsrv.c
@@ -141,32 +141,6 @@ configureTCPListen(tcpsrv_t *pThis, char *cOptarg)
}
-#if 0 // I think this is no longer needed
-static void
-configureTCPListenSessMax(char *cOptarg)
-{
- register int i;
- register char *pArg = cOptarg;
-
- assert(cOptarg != NULL);
-
- /* number of sessions */
- i = 0;
- while(isdigit((int) *pArg)) {
- i = i * 10 + *pArg++ - '0';
- }
-
- if(i > 0)
- pThis->iSessMax = i;
- else {
- /* too small, need to adjust */
- errmsg.LogError(NO_ERRCODE, "TCP session max configured to %s - changing to 1.\n", cOptarg);
- pThis->iSessMax = 1;
- }
-}
-#endif
-
-
/* Initialize the session table
* returns 0 if OK, somewhat else otherwise
*/
@@ -353,7 +327,7 @@ static int *create_tcp_socket(tcpsrv_t *pThis)
/* We need to enable BSD compatibility. Otherwise an attacker
* could flood our log files by sending us tons of ICMP errors.
*/
-#ifndef BSD
+#ifndef OS_BSD
if(net.should_use_so_bsdcompat()) {
if (setsockopt(*s, SOL_SOCKET, SO_BSDCOMPAT,
(char *) &on, sizeof(on)) < 0) {
diff --git a/template.c b/template.c
index 75c9ce7..627f891 100644
--- a/template.c
+++ b/template.c
@@ -188,11 +188,13 @@ static void doSQLEmergencyEscape(register uchar *p, int escapeMode)
* new parameter escapeMode is 0 - standard sql, 1 - "smart" engines
* 2005-09-22 rgerhards
*/
-void doSQLEscape(uchar **pp, size_t *pLen, unsigned short *pbMustBeFreed, int escapeMode)
+rsRetVal
+doSQLEscape(uchar **pp, size_t *pLen, unsigned short *pbMustBeFreed, int escapeMode)
{
+ DEFiRet;
uchar *p;
int iLen;
- cstr_t *pStrB;
+ cstr_t *pStrB = NULL;
uchar *pszGenerated;
assert(pp != NULL);
@@ -210,44 +212,25 @@ void doSQLEscape(uchar **pp, size_t *pLen, unsigned short *pbMustBeFreed, int es
/* when we get out of the loop, we are either at the
* string terminator or the first \'. */
if(*p == '\0')
- return; /* nothing to do in this case! */
+ FINALIZE; /* nothing to do in this case! */
p = *pp;
iLen = *pLen;
- if(rsCStrConstruct(&pStrB) != RS_RET_OK) {
- /* oops - no mem ... Do emergency... */
- doSQLEmergencyEscape(p, escapeMode);
- return;
- }
+ CHKiRet(rsCStrConstruct(&pStrB));
while(*p) {
if(*p == '\'') {
- if(rsCStrAppendChar(pStrB, (escapeMode == 0) ? '\'' : '\\') != RS_RET_OK) {
- doSQLEmergencyEscape(*pp, escapeMode);
- rsCStrDestruct(&pStrB);
- return;
- }
+ CHKiRet(rsCStrAppendChar(pStrB, (escapeMode == 0) ? '\'' : '\\'));
iLen++; /* reflect the extra character */
} else if((escapeMode == 1) && (*p == '\\')) {
- if(rsCStrAppendChar(pStrB, '\\') != RS_RET_OK) {
- doSQLEmergencyEscape(*pp, escapeMode);
- rsCStrDestruct(&pStrB);
- return;
- }
+ CHKiRet(rsCStrAppendChar(pStrB, '\\'));
iLen++; /* reflect the extra character */
}
- if(rsCStrAppendChar(pStrB, *p) != RS_RET_OK) {
- doSQLEmergencyEscape(*pp, escapeMode);
- rsCStrDestruct(&pStrB);
- return;
- }
+ CHKiRet(rsCStrAppendChar(pStrB, *p));
++p;
}
- rsCStrFinish(pStrB);
- if(rsCStrConvSzStrAndDestruct(pStrB, &pszGenerated, 0) != RS_RET_OK) {
- doSQLEmergencyEscape(*pp, escapeMode);
- return;
- }
+ CHKiRet(rsCStrFinish(pStrB));
+ CHKiRet(rsCStrConvSzStrAndDestruct(pStrB, &pszGenerated, 0));
if(*pbMustBeFreed)
free(*pp); /* discard previous value */
@@ -255,6 +238,15 @@ void doSQLEscape(uchar **pp, size_t *pLen, unsigned short *pbMustBeFreed, int es
*pp = pszGenerated;
*pLen = iLen;
*pbMustBeFreed = 1;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ doSQLEmergencyEscape(*pp, escapeMode);
+ if(pStrB != NULL)
+ rsCStrDestruct(&pStrB);
+ }
+
+ RETiRet;
}
@@ -385,7 +377,6 @@ static int do_Constant(unsigned char **pp, struct template *pTpl)
if((pTpe = tpeConstruct(pTpl)) == NULL) {
/* OK, we are out of luck. Let's invalidate the
* entry and that's it.
- * TODO: add panic message once we have a mechanism for this
*/
pTpe->eEntryType = UNDEFINED;
return 1;
@@ -453,6 +444,8 @@ static void doOptions(unsigned char **pp, struct templateEntry *pTpe)
pTpe->data.field.eCaseConv = tplCaseConvLower;
} else if(!strcmp((char*)Buf, "uppercase")) {
pTpe->data.field.eCaseConv = tplCaseConvUpper;
+ } else if(!strcmp((char*)Buf, "sp-if-no-1st-sp")) {
+ pTpe->data.field.options.bSPIffNo1stSP = 1;
} else if(!strcmp((char*)Buf, "escape-cc")) {
pTpe->data.field.options.bEscapeCC = 1;
} else if(!strcmp((char*)Buf, "drop-cc")) {
@@ -510,7 +503,8 @@ static int do_Parameter(unsigned char **pp, struct template *pTpl)
pTpe->eEntryType = FIELD;
while(*p && *p != '%' && *p != ':') {
- rsCStrAppendChar(pStrB, *p++);
+ rsCStrAppendChar(pStrB, tolower(*p));
+ ++p; /* do NOT do this in tolower()! */
}
/* got the name*/
@@ -1021,6 +1015,15 @@ void tplPrintList(void)
if(pTpe->data.field.options.bSpaceCC) {
dbgprintf("[replace control-characters with space] ");
}
+ if(pTpe->data.field.options.bSecPathDrop) {
+ dbgprintf("[slashes are dropped] ");
+ }
+ if(pTpe->data.field.options.bSecPathReplace) {
+ dbgprintf("[slashes are replaced by '_'] ");
+ }
+ if(pTpe->data.field.options.bSPIffNo1stSP) {
+ dbgprintf("[SP iff no first SP] ");
+ }
if(pTpe->data.field.options.bDropLastLF) {
dbgprintf("[drop last LF in msg] ");
}
diff --git a/template.h b/template.h
index 40ccfa5..0226420 100644
--- a/template.h
+++ b/template.h
@@ -80,6 +80,7 @@ struct templateEntry {
unsigned bDropLastLF: 1; /* drop last LF char in msg (PIX!) */
unsigned bSecPathDrop: 1; /* drop slashes, replace dots, empty string */
unsigned bSecPathReplace: 1; /* replace slashes, replace dots, empty string */
+ unsigned bSPIffNo1stSP: 1; /* replace slashes, replace dots, empty string */
} options; /* options as bit fields */
} field;
} data;
@@ -109,7 +110,7 @@ void tplLastStaticInit(struct template *tpl);
* rgerhards, 2007-08-06
*/
rsRetVal tplToString(struct template *pTpl, msg_t *pMsg, uchar** ppSz);
-void doSQLEscape(uchar **pp, size_t *pLen, unsigned short *pbMustBeFreed, int escapeMode);
+rsRetVal doSQLEscape(uchar **pp, size_t *pLen, unsigned short *pbMustBeFreed, int escapeMode);
rsRetVal templateInit();
diff --git a/wti.c b/wti.c
index 8afd250..82cd216 100644
--- a/wti.c
+++ b/wti.c
@@ -371,6 +371,14 @@ wtiWorker(wti_t *pThis)
pthread_yield(); /* see big comment in function header */
# endif
+ /* if we have a rate-limiter set for this worker pool, let's call it. Please
+ * keep in mind that the rate-limiter may hold us for an extended period
+ * of time. -- rgerhards, 2008-04-02
+ */
+ if(pWtp->pfRateLimiter != NULL) {
+ pWtp->pfRateLimiter(pWtp->pUsr);
+ }
+
wtpSetInactivityGuard(pThis->pWtp, 0, LOCK_MUTEX); /* must be set before usr mutex is locked! */
BEGIN_MTX_PROTECTED_OPERATIONS(pWtp->pmutUsr, LOCK_MUTEX);
diff --git a/wtp.c b/wtp.c
index d512626..fcc7589 100644
--- a/wtp.c
+++ b/wtp.c
@@ -546,6 +546,7 @@ DEFpropSetMeth(wtp, pUsr, void*);
DEFpropSetMethPTR(wtp, pmutUsr, pthread_mutex_t);
DEFpropSetMethPTR(wtp, pcondBusy, pthread_cond_t);
DEFpropSetMethFP(wtp, pfChkStopWrkr, rsRetVal(*pVal)(void*, int));
+DEFpropSetMethFP(wtp, pfRateLimiter, rsRetVal(*pVal)(void*));
DEFpropSetMethFP(wtp, pfIsIdle, rsRetVal(*pVal)(void*, int));
DEFpropSetMethFP(wtp, pfDoWork, rsRetVal(*pVal)(void*, void*, int));
DEFpropSetMethFP(wtp, pfOnIdle, rsRetVal(*pVal)(void*, int));
diff --git a/wtp.h b/wtp.h
index 33f4e24..13ebe53 100644
--- a/wtp.h
+++ b/wtp.h
@@ -69,6 +69,7 @@ typedef struct wtp_s {
pthread_mutex_t *pmutUsr;
pthread_cond_t *pcondBusy; /* condition the user will signal "busy again, keep runing" on (awakes worker) */
rsRetVal (*pfChkStopWrkr)(void *pUsr, int);
+ rsRetVal (*pfRateLimiter)(void *pUsr);
rsRetVal (*pfIsIdle)(void *pUsr, int);
rsRetVal (*pfDoWork)(void *pUsr, void *pWti, int);
rsRetVal (*pfOnIdle)(void *pUsr, int);
@@ -100,6 +101,7 @@ rsRetVal wtpShutdownAll(wtp_t *pThis, wtpState_t tShutdownCmd, struct timespec *
int wtpGetCurNumWrkr(wtp_t *pThis, int bLockMutex);
PROTOTYPEObjClassInit(wtp);
PROTOTYPEpropSetMethFP(wtp, pfChkStopWrkr, rsRetVal(*pVal)(void*, int));
+PROTOTYPEpropSetMethFP(wtp, pfRateLimiter, rsRetVal(*pVal)(void*));
PROTOTYPEpropSetMethFP(wtp, pfIsIdle, rsRetVal(*pVal)(void*, int));
PROTOTYPEpropSetMethFP(wtp, pfDoWork, rsRetVal(*pVal)(void*, void*, int));
PROTOTYPEpropSetMethFP(wtp, pfOnIdle, rsRetVal(*pVal)(void*, int));