summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog19
-rw-r--r--Makefile.am4
-rw-r--r--configure.ac20
-rw-r--r--plugins/imdoor/Makefile.am6
-rw-r--r--plugins/imdoor/imdoor.c430
-rw-r--r--plugins/imdoor/sun_cddl.c592
-rw-r--r--plugins/imklog/Makefile.am4
-rw-r--r--plugins/imklog/solaris.c181
-rw-r--r--plugins/imklog/solaris_cddl.c323
-rw-r--r--plugins/imklog/solaris_cddl.h1
-rw-r--r--plugins/imuxsock/imuxsock.c13
-rw-r--r--runtime/Makefile.am1
-rw-r--r--runtime/atomic-posix-sem.c70
-rw-r--r--runtime/atomic.h120
-rw-r--r--runtime/cfsysline.c8
-rw-r--r--runtime/msg.c9
-rw-r--r--runtime/parser.c9
-rw-r--r--runtime/rsyslog.c14
-rw-r--r--solaris/README38
-rw-r--r--solaris/cddllicense.txt242
-rw-r--r--tests/Makefile.am9
-rwxr-xr-xtests/complex1.sh5
-rwxr-xr-xtests/diag.sh17
-rw-r--r--tests/msleep.c50
-rw-r--r--tests/nettester.c15
-rwxr-xr-xtests/random.sh20
-rw-r--r--tests/randomgen.c130
-rw-r--r--tests/rt-init.c2
-rw-r--r--tests/tcpflood.c157
-rw-r--r--tests/testsuites/random.conf13
-rw-r--r--tests/testsuites/samples.snare_ccoff_udp218
-rw-r--r--tools/omfile.c5
-rw-r--r--tools/ompipe.c1
-rw-r--r--tools/syslogd.c6
34 files changed, 2474 insertions, 78 deletions
diff --git a/ChangeLog b/ChangeLog
index bb045fd2..fda427b5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,23 @@
+---------------------------------------------------------------------------
+Version 4.6.3 [v4-stable] (rgerhards), 2010-03-??
+- improvded testbench
+ - added test with truly random data received via syslog to test
+ robustness
+- bugfix: default for $OMFileFlushOnTXEnd was wrong ("off").
+ This, in default mode, caused buffered writing to be used, what
+ means that it looked like no output were written or partial
+ lines. Thanks to Michael Biebl for pointing out this bug.
- bugfix: testbench failed when not executed in UTC+1 timezone
accidently, the time zone information was kept inside some
to-be-checked-for responses
+- temporary bugfix replaced by permanent one for
+ message-induced off-by-one error (potential segfault) (see 4.6.2)
+ The analysis has been completed and a better fix been crafted and
+ integrated.
+- bugfix: the T/P/E config size specifiers did not work properly under
+ all 32-bit platforms
+- bugfix: local unix system log socket was deleted even when it was
+ not configured
---------------------------------------------------------------------------
Version 5.4.1 [v5-stable] (rgerhards), 2010-03-??
- added new property replacer option "date-rfc3164-buggyday" primarily
@@ -348,6 +365,8 @@ Version 4.7.0 [v4-devel] (rgerhards), 2009-09-??
Version 4.6.2 [v4-stable] (rgerhards), 2010-03-26
- new feature: "." action type added to support writing files to relative
pathes (this is primarily meant as a debug aid)
+- added replacements for atomic instructions on systems that do not
+ support them. [backport of Stefen Sledz' patch for v5)
- new feature: $OMFileAsyncWriting directive added
it permits to specifiy if asynchronous writing should be done or not
- bugfix(temporary): message-induced off-by-one error (potential segfault)
diff --git a/Makefile.am b/Makefile.am
index 5f9d35fe..c91c527c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -59,6 +59,10 @@ if ENABLE_IMKLOG
SUBDIRS += plugins/imklog
endif
+if ENABLE_IMDOOR
+SUBDIRS += plugins/imdoor
+endif
+
if ENABLE_GSSAPI
SUBDIRS += plugins/omgssapi plugins/imgssapi
endif
diff --git a/configure.ac b/configure.ac
index 030db218..98deaf5f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -87,6 +87,7 @@ AC_TYPE_UINT8_T
AC_HEADER_TIME
AC_STRUCT_TM
AC_C_VOLATILE
+AC_C_TYPEOF
sa_includes="\
$ac_includes_default
@@ -130,6 +131,9 @@ AC_TRY_COMPILE([
RS_ATOMIC_OPERATIONS
RS_ATOMIC_OPERATIONS_64BIT
+# fall back to POSIX sems for atomic operations (cpu expensive)
+AC_CHECK_HEADERS([semaphore.h])
+
# Additional module directories
AC_ARG_WITH(moddirs,
@@ -279,6 +283,7 @@ AC_ARG_ENABLE(klog,
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)
+AM_CONDITIONAL(ENABLE_IMKLOG_SOLARIS, test x$os_type = xsolaris)
#
@@ -730,6 +735,19 @@ AC_ARG_ENABLE(imfile,
AM_CONDITIONAL(ENABLE_IMFILE, test x$enable_imfile = xyes)
+# settings for the door input module (under solaris, thus default off)
+AC_ARG_ENABLE(imdoor,
+ [AS_HELP_STRING([--enable-imdoor],[door input module enabled @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_imdoor="yes" ;;
+ no) enable_imdoor="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-imdoor) ;;
+ esac],
+ [enable_imdoor=no]
+)
+AM_CONDITIONAL(ENABLE_IMDOOR, test x$enable_imdoor = xyes)
+
+
# settings for the omprog output module
AC_ARG_ENABLE(omprog,
[AS_HELP_STRING([--enable-omprog],[Compiles omprog module @<:@default=no@:>@])],
@@ -891,6 +909,7 @@ AC_CONFIG_FILES([Makefile \
plugins/omstdout/Makefile \
plugins/omruleset/Makefile \
plugins/imfile/Makefile \
+ plugins/imdoor/Makefile \
plugins/imrelp/Makefile \
plugins/imdiag/Makefile \
plugins/omtesting/Makefile \
@@ -924,6 +943,7 @@ echo "---{ input plugins }---"
echo " Klog functionality enabled: $enable_klog ($os_type)"
echo " imdiag enabled: $enable_imdiag"
echo " file input module enabled: $enable_imfile"
+echo " Solaris door input module enabled: $enable_imdoor"
echo " input template module will be compiled: $enable_imtemplate"
echo
echo "---{ output plugins }---"
diff --git a/plugins/imdoor/Makefile.am b/plugins/imdoor/Makefile.am
new file mode 100644
index 00000000..6ad7a904
--- /dev/null
+++ b/plugins/imdoor/Makefile.am
@@ -0,0 +1,6 @@
+pkglib_LTLIBRARIES = imdoor.la
+
+imdoor_la_SOURCES = imdoor.c sun_cddl.c
+imdoor_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+imdoor_la_LDFLAGS = -module -avoid-version
+imdoor_la_LIBADD =
diff --git a/plugins/imdoor/imdoor.c b/plugins/imdoor/imdoor.c
new file mode 100644
index 00000000..83890d03
--- /dev/null
+++ b/plugins/imdoor/imdoor.c
@@ -0,0 +1,430 @@
+/* imdoor.c
+ * This input module is used to receive syslog messages via the Solaris
+ * door mechanism. Not surprisingly, it most probably can not be built
+ * on other platforms.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2010-03-26 by RGerhards
+ *
+ * Copyright 2010 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 <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include "dirty.h"
+#include "cfsysline.h"
+#include "unicode-helper.h"
+#include "module-template.h"
+#include "srUtils.h"
+#include "errmsg.h"
+#include "net.h"
+#include "glbl.h"
+#include "msg.h"
+#include "prop.h"
+
+MODULE_TYPE_INPUT
+
+/* defines */
+#define MAXFUNIX 20
+#ifndef _PATH_LOG
+#ifdef BSD
+#define _PATH_LOG "/var/run/log"
+#else
+#define _PATH_LOG "/dev/log"
+#endif
+#endif
+
+
+/* handle some defines missing on more than one platform */
+#ifndef SUN_LEN
+#define SUN_LEN(su) \
+ (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
+#endif
+/* Module static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(errmsg)
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(prop)
+
+static prop_t *pInputName = NULL; /* our inputName currently is always "imuxsock", and this will hold it */
+static int startIndexUxLocalSockets; /* process funix from that index on (used to
+ * suppress local logging. rgerhards 2005-08-01
+ * read-only after startup
+ */
+static int funixParseHost[MAXFUNIX] = { 0, }; /* should parser parse host name? read-only after startup */
+static int funixFlags[MAXFUNIX] = { IGNDATE, }; /* should parser parse host name? read-only after startup */
+static uchar *funixn[MAXFUNIX] = { (uchar*) _PATH_LOG }; /* read-only after startup */
+static uchar *funixHName[MAXFUNIX] = { NULL, }; /* host-name override - if set, use this instead of actual name */
+static int funixFlowCtl[MAXFUNIX] = { eFLOWCTL_NO_DELAY, }; /* flow control settings for this socket */
+static int funix[MAXFUNIX] = { -1, }; /* read-only after startup */
+static int nfunix = 1; /* number of Unix sockets open / read-only after startup */
+
+/* config settings */
+static int bOmitLocalLogging = 0;
+static uchar *pLogSockName = NULL;
+static uchar *pLogHostName = NULL; /* host name to use with this socket */
+static int bUseFlowCtl = 0; /* use flow control or not (if yes, only LIGHT is used! */
+static int bIgnoreTimestamp = 1; /* ignore timestamps present in the incoming message? */
+
+
+/* set the timestamp ignore / not ignore option for the system
+ * log socket. This must be done separtely, as it is not added via a command
+ * but present by default. -- rgerhards, 2008-03-06
+ */
+static rsRetVal setSystemLogTimestampIgnore(void __attribute__((unused)) *pVal, int iNewVal)
+{
+ DEFiRet;
+ funixFlags[0] = iNewVal ? IGNDATE : NOFLAG;
+ RETiRet;
+}
+
+/* set flowcontrol for the system log socket
+ */
+static rsRetVal setSystemLogFlowControl(void __attribute__((unused)) *pVal, int iNewVal)
+{
+ DEFiRet;
+ funixFlowCtl[0] = iNewVal ? eFLOWCTL_LIGHT_DELAY : eFLOWCTL_NO_DELAY;
+ RETiRet;
+}
+
+/* add an additional listen socket. Socket names are added
+ * until the array is filled up. It is never reset, only at
+ * module unload.
+ * TODO: we should change the array to a list so that we
+ * can support any number of listen socket names.
+ * rgerhards, 2007-12-20
+ * added capability to specify hostname for socket -- rgerhards, 2008-08-01
+ */
+static rsRetVal addLstnSocketName(void __attribute__((unused)) *pVal, uchar *pNewVal)
+{
+ if(nfunix < MAXFUNIX) {
+ if(*pNewVal == ':') {
+ funixParseHost[nfunix] = 1;
+ }
+ else {
+ funixParseHost[nfunix] = 0;
+ }
+ funixHName[nfunix] = pLogHostName;
+ pLogHostName = NULL; /* re-init for next, not freed because funixHName[] now owns it */
+ funixFlowCtl[nfunix] = bUseFlowCtl ? eFLOWCTL_LIGHT_DELAY : eFLOWCTL_NO_DELAY;
+ funixFlags[nfunix] = bIgnoreTimestamp ? IGNDATE : NOFLAG;
+ funixn[nfunix++] = pNewVal;
+ }
+ else {
+ errmsg.LogError(0, NO_ERRCODE, "Out of unix socket name descriptors, ignoring %s\n",
+ pNewVal);
+ }
+
+ return RS_RET_OK;
+}
+
+/* free the funixn[] socket names - needed as cleanup on several places
+ * note that nfunix is NOT reset! funixn[0] is never freed, as it comes from
+ * the constant memory pool - and if not, it is freeed via some other pointer.
+ */
+static rsRetVal discardFunixn(void)
+{
+ int i;
+
+ for (i = 1; i < nfunix; i++) {
+ if(funixn[i] != NULL) {
+ free(funixn[i]);
+ funixn[i] = NULL;
+ }
+ if(funixHName[i] != NULL) {
+ free(funixHName[i]);
+ funixHName[i] = NULL;
+ }
+ }
+
+ return RS_RET_OK;
+}
+
+
+static int create_unix_socket(const char *path)
+{
+ struct sockaddr_un sunx;
+ int fd;
+
+ if (path[0] == '\0')
+ return -1;
+
+ unlink(path);
+
+ memset(&sunx, 0, sizeof(sunx));
+ sunx.sun_family = AF_UNIX;
+ (void) strncpy(sunx.sun_path, path, sizeof(sunx.sun_path));
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (fd < 0 || bind(fd, (struct sockaddr *) &sunx, SUN_LEN(&sunx)) < 0 ||
+ chmod(path, 0666) < 0) {
+ errmsg.LogError(errno, NO_ERRCODE, "connot create '%s'", path);
+ dbgprintf("cannot create %s (%d).\n", path, errno);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+
+/* This function receives data from a socket indicated to be ready
+ * to receive and submits the message received for processing.
+ * rgerhards, 2007-12-20
+ * Interface changed so that this function is passed the array index
+ * of the socket which is to be processed. This eases access to the
+ * growing number of properties. -- rgerhards, 2008-08-01
+ */
+static rsRetVal readSocket(int fd, int iSock)
+{
+ DEFiRet;
+ int iRcvd;
+ int iMaxLine;
+ uchar bufRcv[4096+1];
+ uchar *pRcv = NULL; /* receive buffer */
+
+ assert(iSock >= 0);
+
+ iMaxLine = glbl.GetMaxLine();
+
+ /* we optimize performance: if iMaxLine is below 4K (which it is in almost all
+ * cases, we use a fixed buffer on the stack. Only if it is higher, heap memory
+ * is used. We could use alloca() to achive a similar aspect, but there are so
+ * many issues with alloca() that I do not want to take that route.
+ * rgerhards, 2008-09-02
+ */
+ if((size_t) iMaxLine < sizeof(bufRcv) - 1) {
+ pRcv = bufRcv;
+ } else {
+ CHKmalloc(pRcv = (uchar*) malloc(sizeof(uchar) * (iMaxLine + 1)));
+ }
+
+ iRcvd = recv(fd, pRcv, iMaxLine, 0);
+ dbgprintf("Message from UNIX socket: #%d\n", fd);
+ if (iRcvd > 0) {
+ parseAndSubmitMessage(funixHName[iSock] == NULL ? glbl.GetLocalHostName() : funixHName[iSock],
+ (uchar*)"127.0.0.1", pRcv,
+ iRcvd, funixParseHost[iSock] ? (funixFlags[iSock] | PARSE_HOSTNAME) : funixFlags[iSock],
+ funixFlowCtl[iSock], pInputName, NULL, 0);
+ } else if (iRcvd < 0 && errno != EINTR) {
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ dbgprintf("UNIX socket error: %d = %s.\n", errno, errStr);
+ errmsg.LogError(errno, NO_ERRCODE, "recvfrom UNIX");
+ }
+
+finalize_it:
+ if(pRcv != NULL && (size_t) iMaxLine >= sizeof(bufRcv) - 1)
+ free(pRcv);
+
+ RETiRet;
+}
+
+
+/* This function is called to gather input. */
+BEGINrunInput
+ int maxfds;
+ int nfds;
+ int i;
+ int fd;
+ fd_set readfds;
+CODESTARTrunInput
+ /* this is an endless loop - it is terminated when the thread is
+ * signalled to do so. This, however, is handled by the framework,
+ * right into the sleep below.
+ */
+ while(1) {
+ /* Add the Unix Domain Sockets to the list of read
+ * descriptors.
+ * rgerhards 2005-08-01: we must now check if there are
+ * any local sockets to listen to at all. If the -o option
+ * is given without -a, we do not need to listen at all..
+ */
+ maxfds = 0;
+ FD_ZERO (&readfds);
+ /* Copy master connections */
+ for (i = startIndexUxLocalSockets; i < nfunix; i++) {
+ if (funix[i] != -1) {
+ FD_SET(funix[i], &readfds);
+ if (funix[i]>maxfds) maxfds=funix[i];
+ }
+ }
+
+ if(Debug) {
+ dbgprintf("--------imuxsock calling select, active file descriptors (max %d): ", maxfds);
+ for (nfds= 0; nfds <= maxfds; ++nfds)
+ if ( FD_ISSET(nfds, &readfds) )
+ dbgprintf("%d ", nfds);
+ dbgprintf("\n");
+ }
+
+ /* wait for io to become ready */
+ nfds = select(maxfds+1, (fd_set *) &readfds, NULL, NULL, NULL);
+
+ for (i = 0; i < nfunix && nfds > 0; i++) {
+ if ((fd = funix[i]) != -1 && FD_ISSET(fd, &readfds)) {
+ readSocket(fd, i);
+ --nfds; /* indicate we have processed one */
+ }
+ }
+ }
+
+ RETiRet;
+ENDrunInput
+
+
+BEGINwillRun
+CODESTARTwillRun
+ register int i;
+
+ /* first apply some config settings */
+ startIndexUxLocalSockets = bOmitLocalLogging ? 1 : 0;
+ if(pLogSockName != NULL)
+ funixn[0] = pLogSockName;
+
+ /* initialize and return if will run or not */
+ for (i = startIndexUxLocalSockets ; i < nfunix ; i++) {
+ if ((funix[i] = create_unix_socket((char*) funixn[i])) != -1)
+ dbgprintf("Opened UNIX socket '%s' (fd %d).\n", funixn[i], funix[i]);
+ }
+
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imuxsock"), sizeof("imuxsock") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+
+finalize_it:
+ENDwillRun
+
+
+BEGINafterRun
+CODESTARTafterRun
+ int i;
+ /* do cleanup here */
+ /* Close the UNIX sockets. */
+ for (i = 0; i < nfunix; i++)
+ if (funix[i] != -1)
+ close(funix[i]);
+
+ /* Clean-up files. */
+ for (i = 0; i < nfunix; i++)
+ if (funixn[i] && funix[i] != -1)
+ unlink((char*) funixn[i]);
+ /* free no longer needed string */
+ if(pLogSockName != NULL)
+ free(pLogSockName);
+ if(pLogHostName != NULL) {
+ free(pLogHostName);
+ }
+
+ discardFunixn();
+ nfunix = 1;
+
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
+ENDafterRun
+
+
+BEGINmodExit
+CODESTARTmodExit
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(errmsg, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+ENDqueryEtryPt
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ bOmitLocalLogging = 0;
+ if(pLogSockName != NULL) {
+ free(pLogSockName);
+ pLogSockName = NULL;
+ }
+ if(pLogHostName != NULL) {
+ free(pLogHostName);
+ pLogHostName = NULL;
+ }
+
+ discardFunixn();
+ nfunix = 1;
+ bIgnoreTimestamp = 1;
+ bUseFlowCtl = 0;
+
+ return RS_RET_OK;
+}
+
+
+BEGINmodInit()
+ int i;
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(errmsg, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+
+ dbgprintf("imuxsock version %s initializing\n", PACKAGE_VERSION);
+
+ /* initialize funixn[] array */
+ for(i = 1 ; i < MAXFUNIX ; ++i) {
+ funixn[i] = NULL;
+ funix[i] = -1;
+ }
+
+ /* register config file handlers */
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"omitlocallogging", 0, eCmdHdlrBinary,
+ NULL, &bOmitLocalLogging, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensocketignoremsgtimestamp", 0, eCmdHdlrBinary,
+ NULL, &bIgnoreTimestamp, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"systemlogsocketname", 0, eCmdHdlrGetWord,
+ NULL, &pLogSockName, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensockethostname", 0, eCmdHdlrGetWord,
+ NULL, &pLogHostName, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensocketflowcontrol", 0, eCmdHdlrBinary,
+ NULL, &bUseFlowCtl, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"addunixlistensocket", 0, eCmdHdlrGetWord,
+ addLstnSocketName, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ /* the following one is a (dirty) trick: the system log socket is not added via
+ * an "addUnixListenSocket" config format. As such, it's properties can not be modified
+ * via $InputUnixListenSocket*". So we need to add a special directive
+ * for that. We should revisit all of that once we have the new config format...
+ * rgerhards, 2008-03-06
+ */
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"systemlogsocketignoremsgtimestamp", 0, eCmdHdlrBinary,
+ setSystemLogTimestampIgnore, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"systemlogsocketflowcontrol", 0, eCmdHdlrBinary,
+ setSystemLogFlowControl, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
+/* vim:set ai:
+ */
diff --git a/plugins/imdoor/sun_cddl.c b/plugins/imdoor/sun_cddl.c
new file mode 100644
index 00000000..8e9714d9
--- /dev/null
+++ b/plugins/imdoor/sun_cddl.c
@@ -0,0 +1,592 @@
+#define MAXLINE 4096
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Portions Copyright 2010 by Rainer Gerhards and Adiscon
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
+ * All Rights Reserved
+ */
+
+/*
+ * University Copyright- Copyright (c) 1982, 1986, 1988
+ * The Regents of the University of California
+ * All Rights Reserved
+ *
+ * University Acknowledgment- Portions of this document are derived from
+ * software developed by the University of California, Berkeley, and its
+ * contributors.
+ */
+#include <unistd.h>
+#include <note.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <signal.h>
+#include <string.h>
+#include <strings.h>
+#include <libscf.h>
+#include <netconfig.h>
+#include <netdir.h>
+#include <pwd.h>
+#include <sys/socket.h>
+#include <tiuser.h>
+#include <utmpx.h>
+#include <limits.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <stropts.h>
+#include <assert.h>
+#include <sys/statvfs.h>
+
+#include <sys/param.h>
+#include <sys/sysmacros.h>
+#include <sys/syslog.h>
+#include <sys/strlog.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/utsname.h>
+#include <sys/poll.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
+#include <sys/mman.h>
+#include <sys/note.h>
+#include <door.h>
+#include <sys/door.h>
+
+#include "rsyslog.h"
+#include "debug.h"
+
+#define DOORFILE "/var/run/syslog_door"
+#define RELATIVE_DOORFILE "../var/run/syslog_door"
+#define OLD_DOORFILE "/etc/.syslog_door"
+
+static int DoorFd = -1;
+static int DoorCreated = 0;
+static char *DoorFileName = DOORFILE;
+
+/* for managing door server threads */
+static pthread_mutex_t door_server_cnt_lock = PTHREAD_MUTEX_INITIALIZER;
+static uint_t door_server_cnt = 0;
+static pthread_attr_t door_thr_attr;
+
+/*
+ * the 'server' function that we export via the door. It does
+ * nothing but return.
+ */
+/*ARGSUSED*/
+static void
+server(void *cookie, char *argp, size_t arg_size,
+ door_desc_t *dp, uint_t n)
+{
+ (void) door_return(NULL, 0, NULL, 0);
+ /* NOTREACHED */
+}
+
+/*ARGSUSED*/
+static void *
+create_door_thr(void *arg)
+{
+ (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+ (void) door_return(NULL, 0, NULL, 0);
+
+ /*
+ * If there is an error in door_return(), it will return here and
+ * the thread will exit. Hence we need to decrement door_server_cnt.
+ */
+ (void) pthread_mutex_lock(&door_server_cnt_lock);
+ door_server_cnt--;
+ (void) pthread_mutex_unlock(&door_server_cnt_lock);
+ return (NULL);
+}
+
+/*
+ * Max number of door server threads for syslogd. Since door is used
+ * to check the health of syslogd, we don't need large number of
+ * server threads.
+ */
+#define MAX_DOOR_SERVER_THR 3
+
+/*
+ * Manage door server thread pool.
+ */
+/*ARGSUSED*/
+static void
+door_server_pool(door_info_t *dip)
+{
+ (void) pthread_mutex_lock(&door_server_cnt_lock);
+ if (door_server_cnt <= MAX_DOOR_SERVER_THR &&
+ pthread_create(NULL, &door_thr_attr, create_door_thr, NULL) == 0) {
+ door_server_cnt++;
+ (void) pthread_mutex_unlock(&door_server_cnt_lock);
+ return;
+ }
+
+ (void) pthread_mutex_unlock(&door_server_cnt_lock);
+}
+
+static void
+delete_doorfiles(void)
+{
+ pthread_t mythreadno;
+ struct stat sb;
+ int err;
+ char line[MAXLINE+1];
+
+ if (Debug) {
+ mythreadno = pthread_self();
+ }
+
+
+ if (lstat(DoorFileName, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
+ if (unlink(DoorFileName) < 0) {
+ err = errno;
+ (void) snprintf(line, sizeof (line),
+ "unlink() of %s failed - fatal", DoorFileName);
+ errno = err;
+ DBGPRINTF("%s", line);//logerror(line);
+ DBGPRINTF("delete_doorfiles(%u): error: %s, "
+ "errno=%d\n", mythreadno, line, err);
+ exit(1);
+ }
+
+ DBGPRINTF("delete_doorfiles(%u): deleted %s\n",
+ mythreadno, DoorFileName);
+ }
+
+ if (strcmp(DoorFileName, DOORFILE) == 0) {
+ if (lstat(OLD_DOORFILE, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
+ if (unlink(OLD_DOORFILE) < 0) {
+ err = errno;
+ (void) snprintf(line, sizeof (line),
+ "unlink() of %s failed", OLD_DOORFILE);
+ DBGPRINTF("delete_doorfiles(%u): %s\n",
+ mythreadno, line);
+
+ if (err != EROFS) {
+ errno = err;
+ (void) strlcat(line, " - fatal",
+ sizeof (line));
+ logerror(line);
+ DBGPRINTF("delete_doorfiles(%u): "
+ "error: %s, errno=%d\n",
+ mythreadno, line, err);
+ exit(1);
+ }
+
+ DBGPRINTF("delete_doorfiles(%u): unlink() "
+ "failure OK on RO file system\n",
+ mythreadno);
+ }
+
+ DBGPRINTF("delete_doorfiles(%u): deleted %s\n",
+ mythreadno, OLD_DOORFILE);
+ }
+ }
+
+#if 0
+ if (lstat(PidFileName, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
+ if (unlink(PidFileName) < 0) {
+ err = errno;
+ (void) snprintf(line, sizeof (line),
+ "unlink() of %s failed - fatal", PidFileName);
+ errno = err;
+ logerror(line);
+ DBGPRINTF("delete_doorfiles(%u): error: %s, "
+ "errno=%d\n", mythreadno, line, err);
+ exit(1);
+ }
+
+ DBGPRINTF("delete_doorfiles(%u): deleted %s\n", mythreadno,
+ PidFileName);
+ }
+
+ if (strcmp(PidFileName, PIDFILE) == 0) {
+ if (lstat(OLD_PIDFILE, &sb) == 0 && !S_ISDIR(sb.st_mode)) {
+ if (unlink(OLD_PIDFILE) < 0) {
+ err = errno;
+ (void) snprintf(line, sizeof (line),
+ "unlink() of %s failed", OLD_PIDFILE);
+ DBGPRINTF(5, "delete_doorfiles(%u): %s, \n",
+ mythreadno, line);
+
+ if (err != EROFS) {
+ errno = err;
+ (void) strlcat(line, " - fatal",
+ sizeof (line));
+ logerror(line);
+ DBGPRINTF(1, "delete_doorfiles(%u): "
+ "error: %s, errno=%d\n",
+ mythreadno, line, err);
+ exit(1);
+ }
+
+ DBGPRINTF(5, "delete_doorfiles(%u): unlink "
+ "failure OK on RO file system\n",
+ mythreadno);
+ }
+
+ DBGPRINTF(5, "delete_doorfiles(%u): deleted %s\n",
+ mythreadno, OLD_PIDFILE);
+ }
+ }
+#endif
+
+ if (DoorFd != -1) {
+ (void) door_revoke(DoorFd);
+ }
+
+ DBGPRINTF("delete_doorfiles(%u): revoked door: DoorFd=%d\n",
+ mythreadno, DoorFd);
+}
+
+
+/*
+ * Create the door file and the pid file in /var/run. If the filesystem
+ * containing /etc is writable, create symlinks /etc/.syslog_door and
+ * /etc/syslog.pid to them. On systems that do not support /var/run, create
+ * /etc/.syslog_door and /etc/syslog.pid directly.
+ *
+ * Note: it is not considered fatal to fail to create the pid file or its
+ * symlink. Attempts to use them in the usual way will fail, of course, but
+ * syslogd will function nicely without it (not so for the door file).
+ */
+
+static void
+sun_open_door(void)
+{
+ struct stat buf;
+ door_info_t info;
+ char line[MAXLINE+1];
+ pthread_t mythreadno;
+ int err;
+
+ if (Debug) {
+ mythreadno = pthread_self();
+ }
+
+ /*
+ * first see if another syslogd is running by trying
+ * a door call - if it succeeds, there is already
+ * a syslogd process active
+ */
+
+ if (!DoorCreated) {
+ int door;
+
+ if ((door = open(DoorFileName, O_RDONLY)) >= 0) {
+ DBGPRINTF("open_door(%u): %s opened "
+ "successfully\n", mythreadno, DoorFileName);
+
+ if (door_info(door, &info) >= 0) {
+ DBGPRINTF("open_door(%u): "
+ "door_info:info.di_target = %ld\n",
+ mythreadno, info.di_target);
+
+ if (info.di_target > 0) {
+ (void) sprintf(line, "syslogd pid %ld"
+ " already running. Cannot "
+ "start another syslogd pid %ld",
+ info.di_target, getpid());
+ DBGPRINTF("open_door(%u): error: "
+ "%s\n", mythreadno, line);
+ errno = 0;
+ //logerror(line);
+ exit(1);
+ }
+ }
+
+ (void) close(door);
+ } else {
+ if (lstat(DoorFileName, &buf) < 0) {
+ err = errno;
+
+ DBGPRINTF("open_door(%u): lstat() of %s "
+ "failed, errno=%d\n",
+ mythreadno, DoorFileName, err);
+
+ if ((door = creat(DoorFileName, 0644)) < 0) {
+ err = errno;
+ (void) snprintf(line, sizeof (line),
+ "creat() of %s failed - fatal",
+ DoorFileName);
+ DBGPRINTF("open_door(%u): error: %s, "
+ "errno=%d\n", mythreadno, line,
+ err);
+ errno = err;
+ //logerror(line);
+ delete_doorfiles();
+ exit(1);
+ }
+
+ (void) fchmod(door,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+
+ DBGPRINTF("open_door(%u): creat() of %s "
+ "succeeded\n", mythreadno,
+ DoorFileName);
+
+ (void) close(door);
+ }
+ }
+
+ if (strcmp(DoorFileName, DOORFILE) == 0) {
+ if (lstat(OLD_DOORFILE, &buf) == 0) {
+ DBGPRINTF("open_door(%u): lstat() of %s "
+ "succeeded\n", mythreadno,
+ OLD_DOORFILE);
+
+ if (S_ISDIR(buf.st_mode)) {
+ (void) snprintf(line, sizeof (line),
+ "%s is a directory - fatal",
+ OLD_DOORFILE);
+ DBGPRINTF("open_door(%u): error: "
+ "%s\n", mythreadno, line);
+ errno = 0;
+ //logerror(line);
+ delete_doorfiles();
+ exit(1);
+ }
+
+ DBGPRINTF("open_door(%u): %s is not a "
+ "directory\n",
+ mythreadno, OLD_DOORFILE);
+
+ if (unlink(OLD_DOORFILE) < 0) {
+ err = errno;
+ (void) snprintf(line, sizeof (line),
+ "unlink() of %s failed",
+ OLD_DOORFILE);
+ DBGPRINTF("open_door(%u): %s\n",
+ mythreadno, line);
+
+ if (err != EROFS) {
+ DBGPRINTF("open_door(%u): "
+ "error: %s, "
+ "errno=%d\n",
+ mythreadno, line, err);
+ (void) strcat(line, " - fatal");
+ errno = err;
+ //logerror(line);
+ delete_doorfiles();
+ exit(1);
+ }
+
+ DBGPRINTF("open_door(%u): unlink "
+ "failure OK on RO file "
+ "system\n", mythreadno);
+ }
+ } else {
+ DBGPRINTF("open_door(%u): file %s doesn't "
+ "exist\n", mythreadno, OLD_DOORFILE);
+ }
+
+ if (symlink(RELATIVE_DOORFILE, OLD_DOORFILE) < 0) {
+ err = errno;
+ (void) snprintf(line, sizeof (line),
+ "symlink %s -> %s failed", OLD_DOORFILE,
+ RELATIVE_DOORFILE);
+ DBGPRINTF("open_door(%u): %s\n", mythreadno,
+ line);
+
+ if (err != EROFS) {
+ DBGPRINTF("open_door(%u): error: %s, "
+ "errno=%d\n", mythreadno, line,
+ err);
+ errno = err;
+ (void) strcat(line, " - fatal");
+ //logerror(line);
+ delete_doorfiles();
+ exit(1);
+ }
+
+ DBGPRINTF("open_door(%u): symlink failure OK "
+ "on RO file system\n", mythreadno);
+ } else {
+ DBGPRINTF("open_door(%u): symlink %s -> %s "
+ "succeeded\n", mythreadno,
+ OLD_DOORFILE, RELATIVE_DOORFILE);
+ }
+ }
+
+ if ((DoorFd = door_create(server, 0,
+ DOOR_REFUSE_DESC)) < 0) {
+ //???? DOOR_NO_CANEL requires newer libs??? DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) < 0) {
+ err = errno;
+ (void) sprintf(line, "door_create() failed - fatal");
+ DBGPRINTF("open_door(%u): error: %s, errno=%d\n",
+ mythreadno, line, err);
+ errno = err;
+ //logerror(line);
+ delete_doorfiles();
+ exit(1);
+ }
+ //???? (void) door_setparam(DoorFd, DOOR_PARAM_DATA_MAX, 0);
+ DBGPRINTF("open_door(%u): door_create() succeeded, "
+ "DoorFd=%d\n", mythreadno, DoorFd);
+
+ DoorCreated = 1;
+ }
+
+ (void) fdetach(DoorFileName); /* just in case... */
+
+ (void) door_server_create(door_server_pool);
+
+ if (fattach(DoorFd, DoorFileName) < 0) {
+ err = errno;
+ (void) snprintf(line, sizeof (line), "fattach() of fd"
+ " %d to %s failed - fatal", DoorFd, DoorFileName);
+ DBGPRINTF("open_door(%u): error: %s, errno=%d\n", mythreadno,
+ line, err);
+ errno = err;
+ //logerror(line);
+ delete_doorfiles();
+ exit(1);
+ }
+
+ DBGPRINTF("open_door(%u): attached server() to %s\n", mythreadno,
+ DoorFileName);
+
+#if 0
+ /*
+ * create pidfile anyway, so those using it to control
+ * syslogd (with kill `cat /etc/syslog.pid` perhaps)
+ * don't get broken.
+ */
+
+ if (!PidfileCreated) {
+ int pidfd;
+
+ PidfileCreated = 1;
+
+ if ((pidfd = open(PidFileName, O_RDWR|O_CREAT|O_TRUNC, 0644))
+ < 0) {
+ err = errno;
+ (void) snprintf(line, sizeof (line),
+ "open() of %s failed", PidFileName);
+ DBGPRINTF(1, "open_door(%u): warning: %s, errno=%d\n",
+ mythreadno, line, err);
+ errno = err;
+ //logerror(line);
+ return;
+ }
+
+ (void) fchmod(pidfd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ (void) sprintf(line, "%ld\n", getpid());
+
+ if (write(pidfd, line, strlen(line)) < 0) {
+ err = errno;
+ (void) snprintf(line, sizeof (line),
+ "write to %s on fd %d failed", PidFileName, pidfd);
+ DBGPRINTF(1, "open_door(%u): warning: %s, errno=%d\n",
+ mythreadno, line, err);
+ errno = err;
+ //logerror(line);
+ return;
+ }
+
+ (void) close(pidfd);
+
+ DBGPRINTF("open_door(%u): %s created\n",
+ mythreadno, PidFileName);
+
+ if (strcmp(PidFileName, PIDFILE) == 0) {
+ if (lstat(OLD_PIDFILE, &buf) == 0) {
+ DBGPRINTF("open_door(%u): lstat() of %s "
+ "succeded\n", mythreadno, OLD_PIDFILE);
+
+ if (S_ISDIR(buf.st_mode)) {
+ (void) snprintf(line, sizeof (line),
+ "file %s is a directory",
+ OLD_PIDFILE);
+ DBGPRINTF("open_door(%u): warning: "
+ "%s\n", mythreadno, line);
+ errno = 0;
+ //logerror(line);
+ return;
+ }
+
+ if (unlink(OLD_PIDFILE) < 0) {
+ err = errno;
+ (void) snprintf(line, sizeof (line),
+ "unlink() of %s failed",
+ OLD_PIDFILE);
+ DBGPRINTF("open_door(%u): %s\n",
+ mythreadno, line);
+
+ if (err != EROFS) {
+ DBGPRINTF(1, "open_door (%u): "
+ "warning: %s, "
+ "errno=%d\n",
+ mythreadno, line, err);
+ errno = err;
+ //logerror(line);
+ return;
+ }
+
+ DBGPRINTF(5, "open_door(%u): unlink "
+ "failure OK on RO file "
+ "system\n", mythreadno);
+ }
+ } else {
+ DBGPRINTF("open_door(%u): file %s doesn't "
+ "exist\n", mythreadno, OLD_PIDFILE);
+ }
+
+ if (symlink(RELATIVE_PIDFILE, OLD_PIDFILE) < 0) {
+ err = errno;
+ (void) snprintf(line, sizeof (line),
+ "symlink %s -> %s failed", OLD_PIDFILE,
+ RELATIVE_PIDFILE);
+ DBGPRINTF("open_door(%u): %s\n", mythreadno,
+ line);
+
+ if (err != EROFS) {
+ DBGPRINTF(1, "open_door(%u): warning: "
+ "%s, errno=%d\n", mythreadno,
+ line, err);
+ errno = err;
+ //logerror(line);
+ return;
+ }
+
+ DBGPRINTF(5, "open_door(%u): symlink failure OK "
+ "on RO file system\n", mythreadno);
+ return;
+ }
+
+ DBGPRINTF(5, "open_door(%u): symlink %s -> %s "
+ "succeeded\n", mythreadno, OLD_PIDFILE,
+ RELATIVE_PIDFILE);
+ }
+ }
+#endif
+}
+
+
diff --git a/plugins/imklog/Makefile.am b/plugins/imklog/Makefile.am
index 5d4d0465..06d4013c 100644
--- a/plugins/imklog/Makefile.am
+++ b/plugins/imklog/Makefile.am
@@ -11,6 +11,10 @@ if ENABLE_IMKLOG_LINUX
imklog_la_SOURCES += linux.c module.h ksym.c ksyms.h ksym_mod.c
endif
+if ENABLE_IMKLOG_SOLARIS
+imklog_la_SOURCES += solaris.c solaris_cddl.c
+endif
+
imklog_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
imklog_la_LDFLAGS = -module -avoid-version
imklog_la_LIBADD =
diff --git a/plugins/imklog/solaris.c b/plugins/imklog/solaris.c
new file mode 100644
index 00000000..c2aec30a
--- /dev/null
+++ b/plugins/imklog/solaris.c
@@ -0,0 +1,181 @@
+/* klog driver for solaris
+ *
+ * This contains OS-specific functionality to read the
+ * kernel log. For a general overview, see head comment in
+ * imklog.c.
+ *
+ * This file relies on Sun code in solaris_cddl.c. We have split
+ * it from Sun's code to keep the copyright issue as simple as possible.
+ *
+ * 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.
+ *
+ * If that may be required, an exception is granted to permit linking
+ * this code to the code in solaris_cddl.c that is under the cddl license.
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/socket.h>
+
+
+
+#include "rsyslog.h"
+#include "imklog.h"
+#include "unicode-helper.h"
+#include "solaris_cddl.h"
+
+/* globals */
+static int fklog; // TODO: remove
+#ifndef _PATH_KLOG
+# define _PATH_KLOG "/dev/log"
+#endif
+
+
+static uchar *GetPath(void)
+{
+ return pszPath ? pszPath : UCHAR_CONSTANT(_PATH_KLOG);
+}
+
+/* open the kernel log - will be called inside the willRun() imklog
+ * entry point. -- rgerhards, 2008-04-09
+ */
+rsRetVal
+klogWillRun(void)
+{
+ DEFiRet;
+
+ fklog = sun_openklog((char*) GetPath(), O_RDONLY);
+ if (fklog < 0) {
+ char errStr[1024];
+ int err = errno;
+ rs_strerror_r(err, errStr, sizeof(errStr));
+ DBGPRINTF("error %d opening log socket: %s\n",
+ GetPath(), errStr);
+ 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;
+ int len, i;
+ int iMaxLine;
+ uchar bufRcv[4096+1];
+ uchar *pRcv = NULL; /* receive buffer */
+
+ iMaxLine = klog_getMaxLine();
+
+ /* we optimize performance: if iMaxLine is below 4K (which it is in almost all
+ * cases, we use a fixed buffer on the stack. Only if it is higher, heap memory
+ * is used. We could use alloca() to achive a similar aspect, but there are so
+ * many issues with alloca() that I do not want to take that route.
+ * rgerhards, 2008-09-02
+ */
+ if((size_t) iMaxLine < sizeof(bufRcv) - 1) {
+ pRcv = bufRcv;
+ } else {
+ if((pRcv = (uchar*) malloc(sizeof(uchar) * (iMaxLine + 1))) == NULL)
+ iMaxLine = sizeof(bufRcv) - 1; /* better this than noting */
+ }
+
+ len = 0;
+ for (;;) {
+ dbgprintf("----------imklog(BSD) waiting for kernel log line\n");
+ i = read(fklog, pRcv + len, iMaxLine - len);
+ if (i > 0) {
+ pRcv[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 = pRcv; (q = strchr(p, '\n')) != NULL; p = q + 1) {
+ *q = '\0';
+ Syslog(LOG_INFO, (uchar*) p);
+ }
+ len = strlen(p);
+ if (len >= iMaxLine - 1) {
+ Syslog(LOG_INFO, (uchar*)p);
+ len = 0;
+ }
+ if (len > 0)
+ memmove(pRcv, p, len + 1);
+ }
+ if (len > 0)
+ Syslog(LOG_INFO, pRcv);
+
+ if(pRcv != NULL && (size_t) iMaxLine >= sizeof(bufRcv) - 1)
+ free(pRcv);
+}
+
+
+/* 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;
+ sun_sys_poll();
+ 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/solaris_cddl.c b/plugins/imklog/solaris_cddl.c
new file mode 100644
index 00000000..1053de66
--- /dev/null
+++ b/plugins/imklog/solaris_cddl.c
@@ -0,0 +1,323 @@
+#define MAXLINE 4096
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Portions Copyright 2010 by Rainer Gerhards and Adiscon
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
+ * All Rights Reserved
+ */
+
+/*
+ * University Copyright- Copyright (c) 1982, 1986, 1988
+ * The Regents of the University of California
+ * All Rights Reserved
+ *
+ * University Acknowledgment- Portions of this document are derived from
+ * software developed by the University of California, Berkeley, and its
+ * contributors.
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+#include <sys/poll.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <stropts.h>
+#include <assert.h>
+#include <sys/strlog.h>
+
+#include "rsyslog.h"
+
+static struct pollfd Pfd; /* Pollfd for local the log device */
+
+
+/* findnl_bkwd:
+ * Scans each character in buf until it finds the last newline in buf,
+ * or the scanned character becomes the last COMPLETE character in buf.
+ * Returns the number of scanned bytes.
+ *
+ * buf - pointer to a buffer containing the message string
+ * len - the length of the buffer
+ */
+size_t
+findnl_bkwd(const char *buf, const size_t len)
+{
+ const char *p;
+ size_t mb_cur_max;
+ pthread_t mythreadno;
+
+ if (Debug) {
+ mythreadno = pthread_self();
+ }
+
+ if (len == 0) {
+ return (0);
+ }
+
+ mb_cur_max = MB_CUR_MAX;
+
+ if (mb_cur_max == 1) {
+ /* single-byte locale */
+ for (p = buf + len - 1; p != buf; p--) {
+ if (*p == '\n') {
+ return ((size_t)(p - buf));
+ }
+ }
+ return ((size_t)len);
+ } else {
+ /* multi-byte locale */
+ int mlen;
+ const char *nl;
+ size_t rem;
+
+ p = buf;
+ nl = NULL;
+ for (rem = len; rem >= mb_cur_max; ) {
+ mlen = mblen(p, mb_cur_max);
+ if (mlen == -1) {
+ /*
+ * Invalid character found.
+ */
+ dbgprintf("klog:findnl_bkwd(%u): Invalid MB "
+ "sequence\n", mythreadno);
+ /*
+ * handle as a single byte character.
+ */
+ p++;
+ rem--;
+ } else {
+ /*
+ * It's guaranteed that *p points to
+ * the 1st byte of a multibyte character.
+ */
+ if (*p == '\n') {
+ nl = p;
+ }
+ p += mlen;
+ rem -= mlen;
+ }
+ }
+ if (nl) {
+ return ((size_t)(nl - buf));
+ }
+ /*
+ * no newline nor null byte found.
+ * Also it's guaranteed that *p points to
+ * the 1st byte of a (multibyte) character
+ * at this point.
+ */
+ return (len - rem);
+ }
+}
+//___ end
+
+
+/* Attempts to open the local log device
+ * and return a file descriptor.
+ */
+int
+sun_openklog(char *name, int mode)
+{
+ int fd;
+ struct strioctl str;
+
+ if ((fd = open(name, mode)) < 0) {
+ //logerror("cannot open %s", name);
+ dbgprintf("klog:openklog: cannot open %s (%d)\n",
+ name, errno);
+ return (-1);
+ }
+ str.ic_cmd = I_CONSLOG;
+ str.ic_timout = 0;
+ str.ic_len = 0;
+ str.ic_dp = NULL;
+ if (ioctl(fd, I_STR, &str) < 0) {
+ //logerror("cannot register to log console messages");
+ dbgprintf("klog:openklog: cannot register to log "
+ "console messages (%d)\n", errno);
+ return (-1);
+ }
+ Pfd.fd = fd;
+ Pfd.events = POLLIN;
+ return (fd);
+}
+
+
+/*
+ * Pull up one message from log driver.
+ */
+void
+sun_getkmsg()
+{
+ int flags = 0, i;
+ char *lastline;
+ struct strbuf ctl, dat;
+ struct log_ctl hdr;
+ char buf[MAXLINE+1];
+ size_t buflen;
+ size_t len;
+ char tmpbuf[MAXLINE+1];
+
+ dat.maxlen = MAXLINE;
+ dat.buf = buf;
+ ctl.maxlen = sizeof (struct log_ctl);
+ ctl.buf = (caddr_t)&hdr;
+
+ while ((i = getmsg(Pfd.fd, &ctl, &dat, &flags)) == MOREDATA) {
+ lastline = &dat.buf[dat.len];
+ *lastline = '\0';
+
+ dbgprintf("klog:sys_poll: getmsg: dat.len = %d\n", dat.len);
+ buflen = strlen(buf);
+ len = findnl_bkwd(buf, buflen);
+
+ (void) memcpy(tmpbuf, buf, len);
+ tmpbuf[len] = '\0';
+
+ /* Format sys will enqueue the log message.
+ * Set the sync flag if timeout != 0, which
+ * means that we're done handling all the
+ * initial messages ready during startup.
+ */
+ Syslog(LOG_INFO, buf);
+ /*if (timeout == 0) {
+ formatsys(&hdr, tmpbuf, 0);
+ //sys_init_msg_count++;
+ } else {
+ formatsys(&hdr, tmpbuf, 1);
+ }*/
+
+ if (len != buflen) {
+ /* If anything remains in buf */
+ size_t remlen;
+
+ if (buf[len] == '\n') {
+ /* skip newline */
+ len++;
+ }
+
+ /* Move the remaining bytes to
+ * the beginnning of buf.
+ */
+
+ remlen = buflen - len;
+ (void) memcpy(buf, &buf[len], remlen);
+ dat.maxlen = MAXLINE - remlen;
+ dat.buf = &buf[remlen];
+ } else {
+ dat.maxlen = MAXLINE;
+ dat.buf = buf;
+ }
+ }
+
+ if (i == 0 && dat.len > 0) {
+ dat.buf[dat.len] = '\0';
+ /*
+ * Format sys will enqueue the log message.
+ * Set the sync flag if timeout != 0, which
+ * means that we're done handling all the
+ * initial messages ready during startup.
+ */
+ dbgprintf("klog:getkmsg: getmsg: dat.maxlen = %d\n", dat.maxlen);
+ dbgprintf("klog:getkmsg: getmsg: dat.len = %d\n", dat.len);
+ dbgprintf("klog:getkmsg: getmsg: strlen(dat.buf) = %d\n", strlen(dat.buf));
+ dbgprintf("klog:getkmsg: getmsg: dat.buf = \"%s\"\n", dat.buf);
+ dbgprintf("klog:getkmsg: buf len = %d\n", strlen(buf));
+ //if (timeout == 0) {
+ //formatsys(&hdr, buf, 0);
+ //--sys_init_msg_count++;
+ //} else {
+ //formatsys(&hdr, buf, 1);
+ //}
+ Syslog(LOG_INFO, buf);
+ } else if (i < 0 && errno != EINTR) {
+ if(1){ // (!shutting_down) {
+ dbgprintf("klog:kernel log driver read error");
+ }
+ // TODO trigger retry logic
+ //(void) close(Pfd.fd);
+ //Pfd.fd = -1;
+ }
+}
+
+
+/* this thread listens to the local stream log driver for log messages
+ * generated by this host, formats them, and queues them to the logger
+ * thread.
+ */
+/*ARGSUSED*/
+void *
+sun_sys_poll()
+{
+ int nfds;
+
+ dbgprintf("klog:sys_poll: sys_thread started\n");
+
+ /*
+ * Try to process as many messages as we can without blocking on poll.
+ * We count such "initial" messages with sys_init_msg_count and
+ * enqueue them without the SYNC_FILE flag. When no more data is
+ * waiting on the local log device, we set timeout to INFTIM,
+ * clear sys_init_msg_count, and generate a flush message to sync
+ * the previously counted initial messages out to disk.
+ */
+
+ for (;;) {
+ errno = 0;
+
+ nfds = poll(&Pfd, 1, INFTIM);
+
+ if (nfds == 0)
+ continue;
+
+ if (nfds < 0) {
+ if (errno != EINTR)
+ dbgprintf("klog:poll error");// logerror("poll");
+ continue;
+ }
+ if (Pfd.revents & POLLIN) {
+ sun_getkmsg();
+ } else {
+ // TODO: shutdown, the rsyslog way (in v5!)
+ //if (shutting_down) {
+ //pthread_exit(0);
+ //}
+ if (Pfd.revents & (POLLNVAL|POLLHUP|POLLERR)) {
+ // TODO: trigger retry logic
+/* logerror("kernel log driver poll error");
+ (void) close(Pfd.fd);
+ Pfd.fd = -1;
+ */
+ }
+ }
+
+ }
+ /*NOTREACHED*/
+ return (NULL);
+}
diff --git a/plugins/imklog/solaris_cddl.h b/plugins/imklog/solaris_cddl.h
new file mode 100644
index 00000000..22295658
--- /dev/null
+++ b/plugins/imklog/solaris_cddl.h
@@ -0,0 +1 @@
+int sun_openklog(char *name, int mode);
diff --git a/plugins/imuxsock/imuxsock.c b/plugins/imuxsock/imuxsock.c
index 17c85afb..f3617b47 100644
--- a/plugins/imuxsock/imuxsock.c
+++ b/plugins/imuxsock/imuxsock.c
@@ -350,7 +350,16 @@ CODESTARTwillRun
register int i;
/* first apply some config settings */
- startIndexUxLocalSockets = bOmitLocalLogging ? 1 : 0;
+# ifdef OS_SOLARIS
+ /* under solaris, we must NEVER process the local log socket, because
+ * it is implemented there differently. If we used it, we would actually
+ * delete it and render the system partly unusable. So don't do that.
+ * rgerhards, 2010-03-26
+ */
+ startIndexUxLocalSockets = 1;
+# else
+ startIndexUxLocalSockets = bOmitLocalLogging ? 1 : 0;
+# endif
if(pLogSockName != NULL)
funixn[0] = pLogSockName;
@@ -379,7 +388,7 @@ CODESTARTafterRun
close(funix[i]);
/* Clean-up files. */
- for (i = 0; i < nfunix; i++)
+ for(i = startIndexUxLocalSockets; i < nfunix; i++)
if (funixn[i] && funix[i] != -1)
unlink((char*) funixn[i]);
/* free no longer needed string */
diff --git a/runtime/Makefile.am b/runtime/Makefile.am
index caf7c5ca..fb21c435 100644
--- a/runtime/Makefile.am
+++ b/runtime/Makefile.am
@@ -10,6 +10,7 @@ librsyslog_la_SOURCES = \
unicode-helper.h \
atomic.h \
batch.h \
+ atomic-posix-sem.c \
syslogd-types.h \
module-template.h \
obj-types.h \
diff --git a/runtime/atomic-posix-sem.c b/runtime/atomic-posix-sem.c
new file mode 100644
index 00000000..979fae02
--- /dev/null
+++ b/runtime/atomic-posix-sem.c
@@ -0,0 +1,70 @@
+/* atomic_posix_sem.c: This file supplies an emulation for atomic operations using
+ * POSIX semaphores.
+ *
+ * Copyright 2010 DResearch Digital Media Systems GmbH
+ *
+ * This file is part of the rsyslog runtime library.
+ *
+ * The rsyslog runtime library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The rsyslog runtime library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
+ */
+
+#include "config.h"
+#ifndef HAVE_ATOMIC_BUILTINS
+#ifdef HAVE_SEMAPHORE_H
+#include <semaphore.h>
+#include <errno.h>
+
+#include "atomic.h"
+#include "rsyslog.h"
+#include "srUtils.h"
+
+sem_t atomicSem;
+
+rsRetVal
+atomicSemInit(void)
+{
+ DEFiRet;
+
+ dbgprintf("init posix semaphore for atomics emulation\n");
+ if(sem_init(&atomicSem, 0, 1) == -1)
+ {
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ dbgprintf("init posix semaphore for atomics emulation failed: %s\n", errStr);
+ iRet = RS_RET_SYS_ERR; /* the right error code ??? */
+ }
+
+ RETiRet;
+}
+
+void
+atomicSemExit(void)
+{
+ dbgprintf("destroy posix semaphore for atomics emulation\n");
+ if(sem_destroy(&atomicSem) == -1)
+ {
+ char errStr[1024];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ dbgprintf("destroy posix semaphore for atomics emulation failed: %s\n", errStr);
+ }
+}
+
+#endif /* HAVE_SEMAPHORE_H */
+#endif /* !defined(HAVE_ATOMIC_BUILTINS) */
+
+/* vim:set ai:
+ */
diff --git a/runtime/atomic.h b/runtime/atomic.h
index b507b769..f1152daf 100644
--- a/runtime/atomic.h
+++ b/runtime/atomic.h
@@ -54,6 +54,122 @@
# define ATOMIC_CAS(data, oldVal, newVal) __sync_bool_compare_and_swap(&(data), (oldVal), (newVal));
# define ATOMIC_CAS_VAL(data, oldVal, newVal) __sync_val_compare_and_swap(&(data), (oldVal), (newVal));
#else
+#ifdef HAVE_SEMAPHORE_H
+ /* we use POSIX semaphores instead */
+
+#include "rsyslog.h"
+#include <semaphore.h>
+
+extern sem_t atomicSem;
+rsRetVal atomicSemInit(void);
+void atomicSemExit(void);
+
+#if HAVE_TYPEOF
+#define my_typeof(x) typeof(x)
+#else /* sorry, can't determine types, using 'int' */
+#define my_typeof(x) int
+#endif
+
+# define ATOMIC_SUB(data, val) \
+({ \
+ my_typeof(data) tmp; \
+ sem_wait(&atomicSem); \
+ tmp = data; \
+ data -= val; \
+ sem_post(&atomicSem); \
+ tmp; \
+})
+
+# define ATOMIC_ADD(data, val) \
+({ \
+ my_typeof(data) tmp; \
+ sem_wait(&atomicSem); \
+ tmp = data; \
+ data += val; \
+ sem_post(&atomicSem); \
+ tmp; \
+})
+
+# define ATOMIC_INC_AND_FETCH(data) \
+({ \
+ my_typeof(data) tmp; \
+ sem_wait(&atomicSem); \
+ tmp = data; \
+ data += 1; \
+ sem_post(&atomicSem); \
+ tmp; \
+})
+
+# define ATOMIC_INC(data) ((void) ATOMIC_INC_AND_FETCH(data))
+
+# define ATOMIC_DEC_AND_FETCH(data) \
+({ \
+ sem_wait(&atomicSem); \
+ data -= 1; \
+ sem_post(&atomicSem); \
+ data; \
+})
+
+# define ATOMIC_DEC(data) ((void) ATOMIC_DEC_AND_FETCH(data))
+
+# define ATOMIC_FETCH_32BIT(data) ((unsigned) ATOMIC_ADD((data), 0xffffffff))
+
+# define ATOMIC_STORE_1_TO_32BIT(data) \
+({ \
+ my_typeof(data) tmp; \
+ sem_wait(&atomicSem); \
+ tmp = data; \
+ data = 1; \
+ sem_post(&atomicSem); \
+ tmp; \
+})
+
+# define ATOMIC_STORE_0_TO_INT(data) \
+({ \
+ my_typeof(data) tmp; \
+ sem_wait(&atomicSem); \
+ tmp = data; \
+ data = 0; \
+ sem_post(&atomicSem); \
+ tmp; \
+})
+
+# define ATOMIC_STORE_1_TO_INT(data) \
+({ \
+ my_typeof(data) tmp; \
+ sem_wait(&atomicSem); \
+ tmp = data; \
+ data = 1; \
+ sem_post(&atomicSem); \
+ tmp; \
+})
+
+# define ATOMIC_CAS(data, oldVal, newVal) \
+({ \
+ int ret; \
+ sem_wait(&atomicSem); \
+ if(data != oldVal) ret = 0; \
+ else \
+ { \
+ data = newVal; \
+ ret = 1; \
+ } \
+ sem_post(&atomicSem); \
+ ret; \
+})
+
+# define ATOMIC_CAS_VAL(data, oldVal, newVal) \
+({ \
+ sem_wait(&atomicSem); \
+ if(data == oldVal) \
+ { \
+ data = newVal; \
+ } \
+ sem_post(&atomicSem); \
+ data; \
+})
+
+#else /* not HAVE_SEMAPHORE_H */
/* note that we gained parctical proof that theoretical problems DO occur
* if we do not properly address them. See this blog post for details:
* http://blog.gerhards.net/2009/01/rsyslog-data-race-analysis.html
@@ -67,6 +183,10 @@
# define ATOMIC_DEC_AND_FETCH(data) (--(data))
# define ATOMIC_FETCH_32BIT(data) (data)
# define ATOMIC_STORE_1_TO_32BIT(data) (data) = 1
+# define ATOMIC_STORE_1_TO_INT(data) (data) = 1
+# define ATOMIC_STORE_0_TO_INT(data) (data) = 0
+# define ATOMIC_CAS_VAL(data, oldVal, newVal) (data) = (newVal)
+#endif
#endif
#endif /* #ifndef INCLUDED_ATOMIC_H */
diff --git a/runtime/cfsysline.c b/runtime/cfsysline.c
index 184c0d87..5df8e64c 100644
--- a/runtime/cfsysline.c
+++ b/runtime/cfsysline.c
@@ -217,9 +217,11 @@ static rsRetVal doGetSize(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *
case 'K': i *= 1000; ++(*pp); break;
case 'M': i *= 1000000; ++(*pp); break;
case 'G': i *= 1000000000; ++(*pp); break;
- case 'T': i *= 1000000000000; ++(*pp); break; /* tera */
- case 'P': i *= 1000000000000000; ++(*pp); break; /* peta */
- case 'E': i *= 1000000000000000000; ++(*pp); break; /* exa */
+ /* we need to use the multiplication below because otherwise
+ * the compiler gets an error during constant parsing */
+ case 'T': i *= (int64) 1000 * 1000000000; ++(*pp); break; /* tera */
+ case 'P': i *= (int64) 1000000 * 1000000000; ++(*pp); break; /* peta */
+ case 'E': i *= (int64) 1000000000 * 1000000000; ++(*pp); break; /* exa */
}
/* done */
diff --git a/runtime/msg.c b/runtime/msg.c
index af868102..6424b03a 100644
--- a/runtime/msg.c
+++ b/runtime/msg.c
@@ -2014,6 +2014,8 @@ finalize_it:
/* set raw message in message object. Size of message is provided.
+ * The function makes sure that the stored rawmsg is properly
+ * terminated by '\0'.
* rgerhards, 2009-06-16
*/
void MsgSetRawMsg(msg_t *pThis, char* pszRawMsg, size_t lenMsg)
@@ -2325,13 +2327,6 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
*pPropLen = sizeof("**INVALID PROPERTY NAME**") - 1;
return UCHAR_CONSTANT("**INVALID PROPERTY NAME**");
}
- /* the following line fixes the symptom, but not the root cause -- at least MSG sometimes
- * returns a size of one too less. To prevent all troubles, we recalculate the sizes based
- * on what we actually got. TODO: remove once root cause is found.
- * rgerhards, 2010-03-23
- */
- bufLen = ustrlen(pRes);
-
/* If we did not receive a template pointer, we are already done... */
if(pTpe == NULL) {
diff --git a/runtime/parser.c b/runtime/parser.c
index 38f72986..ca20a11e 100644
--- a/runtime/parser.c
+++ b/runtime/parser.c
@@ -317,7 +317,10 @@ SanitizeMsg(msg_t *pMsg)
pszMsg = pMsg->pszRawMsg;
lenMsg = pMsg->iLenRawMsg;
- /* remove NUL character at end of message (see comment in function header) */
+ /* remove NUL character at end of message (see comment in function header)
+ * Note that we do not need to add a NUL character in this case, because it
+ * is already present ;)
+ */
if(pszMsg[lenMsg-1] == '\0') {
DBGPRINTF("dropped NUL at very end of message\n");
bUpdatedLen = TRUE;
@@ -331,8 +334,9 @@ SanitizeMsg(msg_t *pMsg)
*/
if(bDropTrailingLF && pszMsg[lenMsg-1] == '\n') {
DBGPRINTF("dropped LF at very end of message (DropTrailingLF is set)\n");
- bUpdatedLen = TRUE;
lenMsg--;
+ pszMsg[lenMsg] = '\0';
+ bUpdatedLen = TRUE;
}
/* it is much quicker to sweep over the message and see if it actually
@@ -386,6 +390,7 @@ SanitizeMsg(msg_t *pMsg)
}
++iSrc;
}
+ pDst[iDst] = '\0';
MsgSetRawMsg(pMsg, (char*)pDst, iDst); /* save sanitized string */
diff --git a/runtime/rsyslog.c b/runtime/rsyslog.c
index a76ae25a..921ad0bd 100644
--- a/runtime/rsyslog.c
+++ b/runtime/rsyslog.c
@@ -81,6 +81,7 @@
#include "rule.h"
#include "ruleset.h"
#include "parser.h"
+#include "atomic.h"
/* forward definitions */
static rsRetVal dfltErrLogger(int, uchar *errMsg);
@@ -140,6 +141,12 @@ rsrtInit(char **ppErrObj, obj_if_t *pObjIF)
CHKiRet(objClassInit(NULL)); /* *THIS* *MUST* always be the first class initilizer being called! */
CHKiRet(objGetObjInterface(pObjIF)); /* this provides the root pointer for all other queries */
+#ifndef HAVE_ATOMIC_BUILTINS
+#ifdef HAVE_SEMAPHORE_H
+ CHKiRet(atomicSemInit());
+#endif /* HAVE_SEMAPHORE_H */
+#endif /* !defined(HAVE_ATOMIC_BUILTINS) */
+
/* initialize core classes. We must be very careful with the order of events. Some
* classes use others and if we do not initialize them in the right order, we may end
* up with an invalid call. The most important thing that can happen is that an error
@@ -216,6 +223,13 @@ rsrtExit(void)
glblClassExit();
rulesetClassExit();
ruleClassExit();
+
+#ifndef HAVE_ATOMIC_BUILTINS
+#ifdef HAVE_SEMAPHORE_H
+ atomicSemExit();
+#endif /* HAVE_SEMAPHORE_H */
+#endif /* !defined(HAVE_ATOMIC_BUILTINS) */
+
objClassExit(); /* *THIS* *MUST/SHOULD?* always be the first class initilizer being called (except debug)! */
}
diff --git a/solaris/README b/solaris/README
new file mode 100644
index 00000000..3f88431d
--- /dev/null
+++ b/solaris/README
@@ -0,0 +1,38 @@
+Notes for Solaris
+
+Rsyslog will be fully supported on Solaris in the future. To build it, the GNU build
+tools (and most of the GNU environment) is needed. This software can be
+found at the excellent http://www.blastwave.org site.
+
+PREQUISITES
+It is strongly recommended to use GCC4 with support for
+atomic instructions (if available for the platform). While rsyslog can
+be built without atomic instructin support (and will work well then),
+it then falls back to POSIX semaphores, which require much more CPU
+time than atomic instructions. Note that even on intel platforms the
+(current, as of 2010-03-25) blastwave gcc4 version targets too-old
+processors by default. To change that, use "-imarch=I686" in your
+CFLAGS.
+
+CONFIGURE OPTIONS
+A number of GNU tools are renamed g* so that they not conflict with
+the native Solaris tools. As we need the GNU replacements, this
+must be specified on the ./configure line.
+Also, we must tell the linker where to find the glibc library when
+building the plugins. This is done via the LDFLAGS variable as
+shown below (based on the good information availabe at
+http://prefetch.net/articles/linkers.badldlibrary.html
+
+The working sample configure sequence I use is:
+
+export LDFLAGS="-R/opt/csw/gcc4/lib"
+./configure AR=gar ...other options...
+
+As a "quick and dirty" fix, one may set the following library
+path before executing rsyslog (may be useful to avoid recompile):
+
+export LD_LIBRARY_PATH=/opt/csw/gcc4/lib
+
+NOT YET SUPPORTED
+* local log socket
+* kernel log
diff --git a/solaris/cddllicense.txt b/solaris/cddllicense.txt
new file mode 100644
index 00000000..a10bba27
--- /dev/null
+++ b/solaris/cddllicense.txt
@@ -0,0 +1,242 @@
+ COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL)
+ Version 1.0
+
+
+1. Definitions.
+
+ 1.1. “Contributor” means each individual or entity that creates or contributes to the creation of Modifications.
+
+ 1.2. “Contributor Version” means the combination of the Original Software, prior Modifications used by a Contributor
+ (if any), and the Modifications made by that particular Contributor.
+
+ 1.3. “Covered Software” means (a) the Original Software, or (b) Modifications, or (c) the combination
+ of files containing Original Software with files containing Modifications, in each case including portions thereof.
+
+ 1.4. “Executable” means the Covered Software in any form other than Source Code.
+
+ 1.5. “Initial Developer” means the individual or entity that first makes Original Software available under this License.
+
+ 1.6. “Larger Work” means a work which combines Covered Software or portions thereof with code not governed by the terms
+ of this License.
+
+ 1.7. “License” means this document.
+
+ 1.8. “Licensable” means having the right to grant, to the maximum extent possible, whether at the time of the
+ initial grant or subsequently acquired, any and all of the rights conveyed herein.
+
+ 1.9. “Modifications” means the Source Code and Executable form of any of the following:
+ A. Any file that results from an addition to, deletion from or modification of the contents of a file
+ containing Original Software or previous Modifications;
+ B. Any new file that contains any part of the Original Software or previous Modification; or
+ C. Any new file that is contributed or otherwise made available under the terms of this License.
+
+ 1.10. “Original Software” means the Source Code and Executable form of computer software code that is originally
+ released under this License.
+
+ 1.11. “Patent Claims” means any patent claim(s), now owned or hereafter acquired, including without limitation,
+ method, process, and apparatus claims, in any patent Licensable by grantor.
+
+ 1.12. “Source Code” means (a) the common form of computer software code in which modifications are made and
+ (b) associated documentation included in or with such code.
+
+ 1.13. “You” (or “Your”) means an individual or a legal entity exercising rights under, and complying with all of
+ the terms of, this License. For legal entities, “You” includes any entity which controls, is controlled by, or is
+ under common control with You. For purposes of this definition, “control” means (a) the power, direct or indirect,
+ to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more
+ than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity.
+
+2. License Grants.
+
+ 2.1. The Initial Developer Grant.
+ Conditioned upon Your compliance with Section 3.1 below and subject to third party intellectual property claims,
+ the Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license:
+
+ (a) under intellectual property rights (other than patent or trademark) Licensable by Initial Developer,
+ to use, reproduce, modify, display, perform, sublicense and distribute the Original Software (or portions
+ thereof), with or without Modifications, and/or as part of a Larger Work; and
+
+ (b) under Patent Claims infringed by the making, using or selling of Original Software, to make, have made,
+ use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Software (or portions thereof).
+
+ (c) The licenses granted in Sections 2.1(a) and (b) are effective on the date Initial Developer first
+ distributes or otherwise makes the Original Software available to a third party under the terms of this License.
+
+ (d) Notwithstanding Section 2.1(b) above, no patent license is granted: (1) for code that You delete from
+ the Original Software, or (2) for infringements caused by: (i) the modification of the Original Software,
+ or (ii) the combination of the Original Software with other software or devices.
+
+ 2.2. Contributor Grant.
+ Conditioned upon Your compliance with Section 3.1 below and subject to third party intellectual property claims,
+ each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license:
+
+ (a) under intellectual property rights (other than patent or trademark) Licensable by Contributor to use,
+ reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor
+ (or portions thereof), either on an unmodified basis, with other Modifications, as Covered Software and/or
+ as part of a Larger Work; and
+
+ (b) under Patent Claims infringed by the making, using, or selling of Modifications made by that Contributor
+ either alone and/or in combination with its Contributor Version (or portions of such combination), to make,
+ use, sell, offer for sale, have made, and/or otherwise dispose of: (1) Modifications made by that Contributor
+ (or portions thereof); and (2) the combination of Modifications made by that Contributor with its Contributor
+ Version (or portions of such combination).
+
+ (c) The licenses granted in Sections 2.2(a) and 2.2(b) are effective on the date Contributor first distributes
+ or otherwise makes the Modifications available to a third party.
+
+ (d) Notwithstanding Section 2.2(b) above, no patent license is granted: (1) for any code that Contributor has
+ deleted from the Contributor Version; (2) for infringements caused by: (i) third party modifications of
+ Contributor Version, or (ii) the combination of Modifications made by that Contributor with other software
+ (except as part of the Contributor Version) or other devices; or (3) under Patent Claims infringed by Covered
+ Software in the absence of Modifications made by that Contributor.
+
+3. Distribution Obligations.
+
+ 3.1. Availability of Source Code.
+ Any Covered Software that You distribute or otherwise make available in Executable form must also be made available
+ in Source Code form and that Source Code form must be distributed only under the terms of this License. You must
+ include a copy of this License with every copy of the Source Code form of the Covered Software You distribute or
+ otherwise make available. You must inform recipients of any such Covered Software in Executable form as to how they
+ can obtain such Covered Software in Source Code form in a reasonable manner on or through a medium customarily used
+ for software exchange.
+
+ 3.2. Modifications.
+ The Modifications that You create or to which You contribute are governed by the terms of this License. You
+ represent that You believe Your Modifications are Your original creation(s) and/or You have sufficient rights to
+ grant the rights conveyed by this License.
+
+ 3.3. Required Notices.
+ You must include a notice in each of Your Modifications that identifies You as the Contributor of the Modification.
+ You may not remove or alter any copyright, patent or trademark notices contained within the Covered Software, or
+ any notices of licensing or any descriptive text giving attribution to any Contributor or the Initial Developer.
+
+ 3.4. Application of Additional Terms.
+ You may not offer or impose any terms on any Covered Software in Source Code form that alters or restricts the
+ applicable version of this License or the recipients’ rights hereunder. You may choose to offer, and to charge a
+ fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software.
+ However, you may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor.
+ You must make it absolutely clear that any such warranty, support, indemnity or liability obligation is offered
+ by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability
+ incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability
+ terms You offer.
+
+ 3.5. Distribution of Executable Versions.
+ You may distribute the Executable form of the Covered Software under the terms of this License or under the terms
+ of a license of Your choice, which may contain terms different from this License, provided that You are in compliance
+ with the terms of this License and that the license for the Executable form does not attempt to limit or alter
+ the recipient’s rights in the Source Code form from the rights set forth in this License. If You distribute the
+ Covered Software in Executable form under a different license, You must make it absolutely clear that any terms
+ which differ from this License are offered by You alone, not by the Initial Developer or Contributor. You hereby
+ agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer
+ or such Contributor as a result of any such terms You offer.
+
+ 3.6. Larger Works.
+ You may create a Larger Work by combining Covered Software with other code not governed by the terms of this License
+ and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this
+ License are fulfilled for the Covered Software.
+
+4. Versions of the License.
+
+ 4.1. New Versions.
+ Sun Microsystems, Inc. is the initial license steward and may publish revised and/or new versions of this License
+ from time to time. Each version will be given a distinguishing version number. Except as provided in Section 4.3,
+ no one other than the license steward has the right to modify this License.
+
+ 4.2. Effect of New Versions.
+ You may always continue to use, distribute or otherwise make the Covered Software available under the terms of
+ the version of the License under which You originally received the Covered Software. If the Initial Developer
+ includes a notice in the Original Software prohibiting it from being distributed or otherwise made available under
+ any subsequent version of the License, You must distribute and make the Covered Software available under the terms
+ of the version of the License under which You originally received the Covered Software. Otherwise, You may also
+ choose to use, distribute or otherwise make the Covered Software available under the terms of any subsequent version
+ of the License published by the license steward.
+
+ 4.3. Modified Versions.
+ When You are an Initial Developer and You want to create a new license for Your Original Software, You may create
+ and use a modified version of this License if You: (a) rename the license and remove any references to the name of
+ the license steward (except to note that the license differs from this License); and (b) otherwise make it clear that
+ the license contains terms which differ from this License.
+
+5. DISCLAIMER OF WARRANTY.
+
+COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN “AS IS” BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR
+IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A
+PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED SOFTWARE IS WITH YOU.
+SHOULD ANY COVERED SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
+COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
+NO USE OF ANY COVERED SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+6. TERMINATION.
+
+ 6.1. This License and the rights granted hereunder will terminate automatically if You fail to comply with terms
+ herein and fail to cure such breach within 30 days of becoming aware of the breach. Provisions which, by their
+ nature, must remain in effect beyond the termination of this License shall survive.
+
+ 6.2. If You assert a patent infringement claim (excluding declaratory judgment actions) against Initial Developer
+ or a Contributor (the Initial Developer or Contributor against whom You assert such claim is referred to as
+ “Participant”) alleging that the Participant Software (meaning the Contributor Version where the Participant
+ is a Contributor or the Original Software where the Participant is the Initial Developer) directly or
+ indirectly infringes any patent, then any and all rights granted directly or indirectly to You by such Participant,
+ the Initial Developer (if the Initial Developer is not the Participant) and all Contributors under Sections 2.1
+ and/or 2.2 of this License shall, upon 60 days notice from Participant terminate prospectively and automatically
+ at the expiration of such 60 day notice period, unless if within such 60 day period You withdraw Your claim with
+ respect to the Participant Software against such Participant either unilaterally or pursuant to a written agreement
+ with Participant.
+
+ 6.3. If You assert a patent infringement claim against Participant alleging that the Participant Software directly
+ or indirectly infringes any patent where such claim is resolved (such as by license or settlement) prior to the
+ initiation of patent infringement litigation, then the reasonable value of the licenses granted by such Participant
+ under Sections 2.1 or 2.2 shall be taken into account in determining the amount or value of any payment or license.
+
+ 6.4. In the event of termination under Sections 6.1 or 6.2 above, all end user licenses that have been validly granted
+ by You or any distributor hereunder prior to termination (excluding licenses granted to You by any distributor)
+ shall survive termination.
+
+7. LIMITATION OF LIABILITY.
+
+UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE
+INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO
+ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR
+LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY
+SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL
+INJURY RESULTING FROM SUCH PARTY’S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+8. U.S. GOVERNMENT END USERS.
+
+The Covered Software is a “commercial item,” as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of
+“commercial computer software” (as that term is defined at 48 C.F.R. § 252.227-7014(a)(1)) and “commercial computer software documentation”
+as such terms are used in 48 C.F.R. 12.212 Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
+all U.S. Government End Users acquire Covered Software with only those rights set forth herein. This U.S. Government Rights clause is in lieu of,
+and supersedes, any other FAR, DFAR, or other clause or provision that addresses Government rights in computer software under this License.
+
+9. MISCELLANEOUS.
+
+This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed
+by the law of the jurisdiction specified in a notice contained within the Original Software (except to the extent applicable law, if any,
+provides otherwise), excluding such jurisdiction’s conflict-of-law provisions. Any litigation relating to this License shall be subject
+to the jurisdiction of the courts located in the jurisdiction and venue specified in a notice contained within the Original Software, with the
+losing party responsible for costs, including, without limitation, court costs and reasonable attorneys’ fees and expenses. The application of
+the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that
+the language of a contract shall be construed against the drafter shall not apply to this License. You agree that You alone are responsible for
+compliance with the United States export administration regulations (and the export control laws and regulation of any other countries) when You use,
+distribute or otherwise make available any Covered Software.
+
+10. RESPONSIBILITY FOR CLAIMS.
+
+As between Initial Developer and the Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of
+its utilization of rights under this License and You agree to work with Initial Developer and Contributors to distribute such responsibility on
+an equitable basis. Nothing herein is intended or shall be deemed to constitute any admission of liability.
+
+--------
+
+NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION
+LICENSE (CDDL)
+
+The OpenSolaris code released under the CDDL shall be governed by the laws
+of the State of California (excluding conflict-of-law provisions). Any
+litigation relating to this License shall be subject to the jurisdiction of
+the Federal Courts of the Northern District of California and the state
+courts of the State of California, with venue lying in Santa Clara County,
+California.
+
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 747b10cf..e2e3d69b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,6 +1,6 @@
if ENABLE_TESTBENCH
TESTRUNS = rt_init rscript
-check_PROGRAMS = $(TESTRUNS) ourtail nettester tcpflood chkseq
+check_PROGRAMS = $(TESTRUNS) ourtail nettester tcpflood chkseq msleep randomgen
TESTS = $(TESTRUNS) cfg.sh \
arrayqueue.sh \
linkedlistqueue.sh \
@@ -32,6 +32,7 @@ TESTS = $(TESTRUNS) cfg.sh \
dynfile_invld_sync.sh \
dynfile_invalid2.sh \
complex1.sh \
+ random.sh \
queue-persist.sh \
pipeaction.sh \
execonlyonce.sh \
@@ -229,6 +230,8 @@ EXTRA_DIST= 1.rstest 2.rstest 3.rstest err1.rstest \
testsuites/gzipwr_large_dynfile.conf \
complex1.sh \
testsuites/complex1.conf \
+ random.sh \
+ testsuites/random.conf \
dynfile_invld_async.sh \
dynfile_invld_sync.sh \
dynfile_cachemiss.sh \
@@ -256,11 +259,15 @@ EXTRA_DIST= 1.rstest 2.rstest 3.rstest err1.rstest \
cfg.sh
ourtail_SOURCES = ourtail.c
+msleep_SOURCES = msleep.c
chkseq_SOURCES = chkseq.c
tcpflood_SOURCES = tcpflood.c
tcpflood_LDADD = $(SOL_LIBS)
+randomgen_SOURCES = randomgen.c
+randomgen_LDADD = $(SOL_LIBS)
+
nettester_SOURCES = nettester.c getline.c
nettester_LDADD = $(SOL_LIBS)
diff --git a/tests/complex1.sh b/tests/complex1.sh
index b5dc2c9d..7395bf21 100755
--- a/tests/complex1.sh
+++ b/tests/complex1.sh
@@ -10,12 +10,13 @@ source $srcdir/diag.sh init
export RSYSLOG_DEBUG="debug nostdout"
export RSYSLOG_DEBUGLOG="log"
source $srcdir/diag.sh startup complex1.conf
-# send 30,000 messages of 400 bytes plus header max, via three dest ports
+# send 40,000 messages of 400 bytes plus header max, via three dest ports
source $srcdir/diag.sh tcpflood -m40000 -rd400 -P129 -f5 -n3 -c15 -i1
sleep 2 # due to large messages, we need this time for the tcp receiver to settle...
source $srcdir/diag.sh shutdown-when-empty # shut down rsyslogd when done processing messages
source $srcdir/diag.sh wait-shutdown # and wait for it to terminate
ls rsyslog.out.*.log
-zcat rsyslog.out.*.log > rsyslog.out.log
+source $srcdir/diag.sh setzcat # find out which zcat to use
+$ZCAT rsyslog.out.*.log > rsyslog.out.log
source $srcdir/diag.sh seq-check 1 40000 -E
source $srcdir/diag.sh exit
diff --git a/tests/diag.sh b/tests/diag.sh
index 40b8db2e..53b06243 100755
--- a/tests/diag.sh
+++ b/tests/diag.sh
@@ -17,7 +17,7 @@ case $1 in
cp $srcdir/testsuites/diag-common.conf diag-common.conf
cp $srcdir/testsuites/diag-common2.conf diag-common2.conf
rm -f rsyslog.action.*.include
- rm -f rsyslogd.started work-*.conf
+ rm -f rsyslogd.started work-*.conf rsyslog.random.data
rm -f rsyslogd2.started work-*.conf
rm -f work rsyslog.out.log rsyslog.out.log.save # common work files
rm -f rsyslog.out.*.log
@@ -28,7 +28,7 @@ case $1 in
'exit') rm -f rsyslogd.started work-*.conf diag-common.conf
rm -f rsyslogd2.started diag-common2.conf rsyslog.action.*.include
rm -f work rsyslog.out.log rsyslog.out.log.save # common work files
- rm -f rsyslog.out.*.log
+ rm -f rsyslog.out.*.log rsyslog.random.data
rm -rf test-spool
echo -------------------------------------------------------------------------------
;;
@@ -39,16 +39,14 @@ case $1 in
;;
'wait-startup') # wait for rsyslogd startup ($2 is the instance)
while test ! -f rsyslogd$2.started; do
- #true
- sleep 0.1 # if this is not supported by all platforms, use above!
+ ./msleep 100 # wait 100 milliseconds
done
echo "rsyslogd$2 started with pid " `cat rsyslog$2.pid`
;;
'wait-shutdown') # actually, we wait for rsyslog.pid to be deleted. $2 is the
# instance
while test -f rsyslog$2.pid; do
- #true
- sleep 0.1 # if this is not supported by all platforms, use above!
+ ./msleep 100 # wait 100 milliseconds
done
if [ -e core.* ]
then
@@ -139,5 +137,12 @@ case $1 in
exit 1
fi
;;
+ 'setzcat') # find out name of zcat tool
+ if [ `uname` == SunOS ]; then
+ ZCAT=gzcat
+ else
+ ZCAT=zcat
+ fi
+ ;;
*) echo "invalid argument" $1
esac
diff --git a/tests/msleep.c b/tests/msleep.c
new file mode 100644
index 00000000..6fa57b79
--- /dev/null
+++ b/tests/msleep.c
@@ -0,0 +1,50 @@
+/* sleeps for the specified number of MILLIseconds.
+ * Primarily meant as a portable tool available everywhere for the
+ * testbench (sleep 0.1 does not work on all platforms).
+ *
+ * Part of the testbench for rsyslog.
+ *
+ * Copyright 2010 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 <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[])
+{
+ struct timeval tvSelectTimeout;
+ long sleepTime;
+
+ if(argc != 2) {
+ fprintf(stderr, "usage: msleep <milliseconds>\n");
+ exit(1);
+ }
+
+ sleepTime = atoi(argv[1]);
+ tvSelectTimeout.tv_sec = sleepTime / 1000;
+ tvSelectTimeout.tv_usec = (sleepTime % 1000) * 1000; /* micro seconds */
+ if(select(0, NULL, NULL, NULL, &tvSelectTimeout) == -1) {
+ perror("select");
+ exit(1);
+ }
+
+ return 0;
+}
+
diff --git a/tests/nettester.c b/tests/nettester.c
index 6932381e..e12758a8 100644
--- a/tests/nettester.c
+++ b/tests/nettester.c
@@ -64,7 +64,7 @@ static int iPort = 12514; /* port which shall be used for sending data */
static char* pszCustomConf = NULL; /* custom config file, use -c conf to specify */
static int verbose = 0; /* verbose output? -v option */
static int IPv4Only = 0; /* use only IPv4 in rsyslogd call? */
-static int useDebugEnv = 0; /* activate debugging environment (for rsyslog debug log)? */
+static char **ourEnvp;
/* these two are quick hacks... */
int iFailed = 0;
@@ -226,9 +226,6 @@ int openPipe(char *configFile, pid_t *pid, int *pfd)
char *newargv[] = {"../tools/rsyslogd", "dummy", "-c4", "-u2", "-n", "-irsyslog.pid",
"-M../runtime/.libs:../.libs", NULL, NULL};
char confFile[1024];
- char *newenviron[] = { NULL };
- char *newenvironDeb[] = { "RSYSLOG_DEBUG=debug nostdout",
- "RSYSLOG_DEBUGLOG=log", NULL };
sprintf(confFile, "-f%s/testsuites/%s.conf", srcdir,
(pszCustomConf == NULL) ? configFile : pszCustomConf);
@@ -254,7 +251,7 @@ int openPipe(char *configFile, pid_t *pid, int *pfd)
close(pipefd[1]);
close(pipefd[0]);
fclose(stdin);
- execve("../tools/rsyslogd", newargv, (useDebugEnv) ? newenvironDeb : newenviron);
+ execve("../tools/rsyslogd", newargv, ourEnvp);
} else {
close(pipefd[1]);
*pid = cpid;
@@ -478,7 +475,7 @@ void doAtExit(void)
* of this file.
* rgerhards, 2009-04-03
*/
-int main(int argc, char *argv[])
+int main(int argc, char *argv[], char *envp[])
{
int fd;
int opt;
@@ -487,7 +484,8 @@ int main(int argc, char *argv[])
char buf[4096];
char testcases[4096];
- while((opt = getopt(argc, argv, "4dc:i:p:t:v")) != EOF) {
+ ourEnvp = envp;
+ while((opt = getopt(argc, argv, "4c:i:p:t:v")) != EOF) {
switch((char)opt) {
case '4':
IPv4Only = 1;
@@ -495,9 +493,6 @@ int main(int argc, char *argv[])
case 'c':
pszCustomConf = optarg;
break;
- case 'd':
- useDebugEnv = 1;
- break;
case 'i':
if(!strcmp(optarg, "udp"))
inputMode = inputUDP;
diff --git a/tests/random.sh b/tests/random.sh
new file mode 100755
index 00000000..79f704c7
--- /dev/null
+++ b/tests/random.sh
@@ -0,0 +1,20 @@
+# Test if rsyslog survives sending truely random data to it...
+#
+# added 2010-04-01 by Rgerhards
+# This file is part of the rsyslog project, released under GPLv3
+echo ===============================================================================
+echo TEST: \[random.sh\]: testing random data
+source $srcdir/diag.sh init
+# uncomment for debugging support:
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
+#export RSYSLOG_DEBUGLOG="log"
+source $srcdir/diag.sh startup random.conf
+# generate random data
+./randomgen -f rsyslog.random.data -s 100000
+ls -l rsyslog.random.data
+source $srcdir/diag.sh tcpflood -B -I rsyslog.random.data -c5 -C10
+source $srcdir/diag.sh shutdown-when-empty # shut down rsyslogd when done processing messages
+source $srcdir/diag.sh wait-shutdown # and wait for it to terminate
+# we do not check anything yet, the point is if rsyslog survived ;)
+# TODO: check for exit message, but we'll notice an abort anyhow, so not that important
+#source $srcdir/diag.sh exit
diff --git a/tests/randomgen.c b/tests/randomgen.c
new file mode 100644
index 00000000..9ba56954
--- /dev/null
+++ b/tests/randomgen.c
@@ -0,0 +1,130 @@
+/* generates random data for later use in test cases. Of course,
+ * we could generate random data during the testcase itself, but
+ * the core idea is that we record the random data so that we have
+ * a chance to reproduce a problem should it occur. IMHO this
+ * provides the best compromise, by a) having randomness but
+ * b) knowing what was used during the test.
+ *
+ * Params
+ * -f output file name (stdout if not given)
+ * -s size of test data, plain number is size in k, 1MB default
+ * -u uses /dev/urandom instead of libc random number generator
+ * (when available). Note that this is usually much slower.
+ *
+ * Part of the testbench for rsyslog.
+ *
+ * Copyright 2010 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 <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <assert.h>
+#include <unistd.h>
+#include <string.h>
+#include <netinet/in.h>
+
+#define EXIT_FAILURE 1
+
+static char *fileName = NULL; /* name of output file */
+static int tryUseURandom = 0; /* try to use /dev/urandom? */
+static long long fileSize = 1024*1024; /* file size in K, 1MB default */
+
+
+/* generate the random file. This code really can be improved (e.g. read /dev/urandom
+ * when available)
+ */
+static inline void
+genFile()
+{
+ long i;
+ FILE *fp;
+ FILE *rfp = NULL;
+
+ if(fileName == NULL) {
+ fp = stdout;
+ } else {
+ if((fp = fopen(fileName, "w")) == NULL) {
+ perror(fileName);
+ }
+ }
+
+ /* try to use /dev/urandom, if available */
+ if(tryUseURandom)
+ rfp = fopen("/dev/urandom", "r");
+
+ if(rfp == NULL) {
+ /* fallback, use libc random number generator */
+ for(i = 0 ; i < fileSize ; ++i) {
+ if(fputc((char) rand(), fp) == EOF) {
+ perror(fileName);
+ exit(1);
+ }
+ }
+ } else {
+ /* use /dev/urandom */
+ printf("using /dev/urandom");
+ for(i = 0 ; i < fileSize ; ++i) {
+ if(fputc(fgetc(rfp), fp) == EOF) {
+ perror(fileName);
+ exit(1);
+ }
+ }
+ }
+
+ if(fileName != NULL)
+ fclose(fp);
+}
+
+
+/* Run the test.
+ * rgerhards, 2009-04-03
+ */
+int main(int argc, char *argv[])
+{
+ int ret = 0;
+ int opt;
+
+ srand(time(NULL)); /* seed is good enough for our needs */
+
+ while((opt = getopt(argc, argv, "f:s:u")) != -1) {
+ switch (opt) {
+ case 'f': fileName = optarg;
+ break;
+ case 's': fileSize = atol(optarg) * 1024;
+ break;
+ case 'u': tryUseURandom = 1;
+ break;
+ default: printf("invalid option '%c' or value missing - terminating...\n", opt);
+ exit (1);
+ break;
+ }
+ }
+
+ printf("generating random data file '%s' of %ldkb - may take a short while...\n",
+ fileName, (long) (fileSize / 1024));
+ genFile();
+
+ exit(ret);
+}
diff --git a/tests/rt-init.c b/tests/rt-init.c
index 66a9ad32..dbe94b4a 100644
--- a/tests/rt-init.c
+++ b/tests/rt-init.c
@@ -39,6 +39,6 @@ ENDExit
BEGINTest
CODESTARTTest
-finalize_it:
+/*finalize_it:*/
/* room for custom error reporter, leave blank if not needed */
ENDTest
diff --git a/tests/tcpflood.c b/tests/tcpflood.c
index 32bf959d..e92d1308 100644
--- a/tests/tcpflood.c
+++ b/tests/tcpflood.c
@@ -20,6 +20,14 @@
* one field to the right. Zero (default) disables this functionality.
* -M the message to be sent. Disables all message format options, as
* only that exact same message is sent.
+ * -I read specified input file, do NOT generate own test data. The test
+ * completes when eof is reached.
+ * -B The specified file (-I) is binary. No data processing is done by
+ * tcpflood. If multiple connections are specified, data is read in
+ * chunks and spread across the connections without taking any record
+ * delemiters into account.
+ * -C when input from a file is read, this file is transmitted -C times
+ * (C like cycle, running out of meaningful option switches ;))
*
* Part of the testbench for rsyslog.
*
@@ -54,6 +62,7 @@
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
+#include <sys/resource.h>
#define EXIT_FAILURE 1
#define INVALID_SOCKET -1
@@ -75,6 +84,10 @@ static int *sockArray; /* array of sockets to use */
static int msgNum = 0; /* initial message number to start with */
static int bShowProgress = 1; /* show progress messages */
static char *MsgToSend = NULL; /* if non-null, this is the actual message to send */
+static int bBinaryFile = 0; /* is -I file binary */
+static char *dataFile = NULL; /* name of data file, if NULL, generate own data */
+static int numFileIterations = 1;/* how often is file data to be sent? */
+FILE *dataFP = NULL; /* file pointer for data file, if used */
/* open a single tcp connection
@@ -166,8 +179,8 @@ int openConnections(void)
void closeConnections(void)
{
int i;
- char msgBuf[128];
size_t lenMsg;
+ char msgBuf[128];
if(bShowProgress)
write(1, " close connections", sizeof(" close connections")-1);
@@ -186,6 +199,62 @@ void closeConnections(void)
}
+/* generate the message to be sent according to program command line parameters.
+ * this has been moved to its own function as we now have various different ways
+ * of constructing test messages. -- rgerhards, 2010-03-31
+ */
+static inline void
+genMsg(char *buf, size_t maxBuf, int *pLenBuf)
+{
+ int edLen; /* actual extra data length to use */
+ char extraData[MAX_EXTRADATA_LEN + 1];
+ char dynFileIDBuf[128] = "";
+ static int numMsgsGen = 0;
+ int done;
+
+ if(dataFP != NULL) {
+ /* get message from file */
+ do {
+ done = 1;
+ *pLenBuf = fread(buf, 1, 1024, dataFP);
+ if(feof(dataFP)) {
+ if(--numFileIterations > 0) {
+ rewind(dataFP);
+ done = 0; /* need new iteration */
+ } else {
+ *pLenBuf = 0;
+ goto finalize_it;
+ }
+ }
+ } while(!done); /* Attention: do..while()! */
+ } else if(MsgToSend == NULL) {
+ if(dynFileIDs > 0) {
+ snprintf(dynFileIDBuf, maxBuf, "%d:", rand() % dynFileIDs);
+ }
+ if(extraDataLen == 0) {
+ *pLenBuf = snprintf(buf, maxBuf, "<%s>Mar 1 01:00:00 172.20.245.8 tag msgnum:%s%8.8d:\n",
+ msgPRI, dynFileIDBuf, msgNum);
+ } else {
+ if(bRandomizeExtraData)
+ edLen = ((long) rand() + extraDataLen) % extraDataLen + 1;
+ else
+ edLen = extraDataLen;
+ memset(extraData, 'X', edLen);
+ extraData[edLen] = '\0';
+ *pLenBuf = snprintf(buf, maxBuf, "<%s>Mar 1 01:00:00 172.20.245.8 tag msgnum:%s%8.8d:%d:%s\n",
+ msgPRI, dynFileIDBuf, msgNum, edLen, extraData);
+ }
+ } else {
+ /* use fixed message format from command line */
+ *pLenBuf = snprintf(buf, maxBuf, "%s\n", MsgToSend);
+ }
+
+ if(numMsgsGen++ >= numMsgsToSend)
+ *pLenBuf = 0; /* indicate end of run */
+
+finalize_it: ;
+}
+
/* send messages to the tcp connections we keep open. We use
* a very basic format that helps identify the message
* (via msgnum:<number>: e.g. msgnum:00000001:). This format is suitable
@@ -196,52 +265,42 @@ void closeConnections(void)
*/
int sendMessages(void)
{
- int i;
+ int i = 0;
int socknum;
int lenBuf;
int lenSend;
- int edLen; /* actual extra data length to use */
- char dynFileIDBuf[128] = "";
+ char *statusText;
char buf[MAX_EXTRADATA_LEN + 1024];
- char extraData[MAX_EXTRADATA_LEN + 1];
- printf("Sending %d messages.\n", numMsgsToSend);
+ if(dataFile == NULL) {
+ printf("Sending %d messages.\n", numMsgsToSend);
+ statusText = "messages";
+ } else {
+ printf("Sending file '%s' %d times.\n", dataFile, numFileIterations);
+ statusText = "kb";
+ }
if(bShowProgress)
- printf("\r%8.8d messages sent", 0);
- for(i = 0 ; i < numMsgsToSend ; ++i) {
+ printf("\r%8.8d %s sent", 0, statusText);
+ while(1) { /* broken inside loop! */
if(i < numConnections)
socknum = i;
else if(i >= numMsgsToSend - numConnections)
socknum = i - (numMsgsToSend - numConnections);
- else
- socknum = rand() % numConnections;
- if(MsgToSend == NULL) {
- if(dynFileIDs > 0) {
- sprintf(dynFileIDBuf, "%d:", rand() % dynFileIDs);
- }
- if(extraDataLen == 0) {
- lenBuf = sprintf(buf, "<%s>Mar 1 01:00:00 172.20.245.8 tag msgnum:%s%8.8d:\n",
- msgPRI, dynFileIDBuf, msgNum);
- } else {
- if(bRandomizeExtraData)
- edLen = ((long) rand() + extraDataLen) % extraDataLen + 1;
- else
- edLen = extraDataLen;
- memset(extraData, 'X', edLen);
- extraData[edLen] = '\0';
- lenBuf = sprintf(buf, "<%s>Mar 1 01:00:00 172.20.245.8 tag msgnum:%s%8.8d:%d:%s\n",
- msgPRI, dynFileIDBuf, msgNum, edLen, extraData);
- }
- } else {
- /* use fixed message format from command line */
- lenBuf = sprintf(buf, "%s\n", MsgToSend);
+ else {
+ int rnd = rand();
+ //socknum = rand() % numConnections;
+ socknum = rnd % numConnections;
}
+ genMsg(buf, sizeof(buf), &lenBuf); /* generate the message to send according to params */
+ if(lenBuf == 0)
+ break; /* end of processing! */
lenSend = send(sockArray[socknum], buf, lenBuf, 0);
if(lenSend != lenBuf) {
printf("\r%5.5d\n", i);
fflush(stdout);
perror("send test data");
- printf("send() failed at socket %d, index %d, msgNum %d\n", socknum, i, msgNum);
+ printf("send() failed at socket %d, index %d, msgNum %d\n",
+ sockArray[socknum], i, msgNum);
fflush(stderr);
return(1);
}
@@ -250,8 +309,9 @@ int sendMessages(void)
printf("\r%8.8d", i);
}
++msgNum;
+ ++i;
}
- printf("\r%8.8d messages sent\n", i);
+ printf("\r%8.8d %s sent\n", i, statusText);
return 0;
}
@@ -335,7 +395,7 @@ int main(int argc, char *argv[])
if(!isatty(1))
bShowProgress = 0;
- while((opt = getopt(argc, argv, "f:t:p:c:m:i:P:d:n:M:r")) != -1) {
+ while((opt = getopt(argc, argv, "f:t:p:c:C:m:i:I:P:d:n:M:rB")) != -1) {
switch (opt) {
case 't': targetIP = optarg;
break;
@@ -345,6 +405,8 @@ int main(int argc, char *argv[])
break;
case 'c': numConnections = atoi(optarg);
break;
+ case 'C': numFileIterations = atoi(optarg);
+ break;
case 'm': numMsgsToSend = atoi(optarg);
break;
case 'i': msgNum = atoi(optarg);
@@ -364,12 +426,41 @@ int main(int argc, char *argv[])
break;
case 'M': MsgToSend = optarg;
break;
+ case 'I': dataFile = optarg;
+ /* in this mode, we do not know the num messages to send, so
+ * we set a (high) number to keep the code happy.
+ */
+ numMsgsToSend = 1000000;
+ break;
+ case 'B': bBinaryFile = 1;
+ break;
default: printf("invalid option '%c' or value missing - terminating...\n", opt);
exit (1);
break;
}
}
+ if(numConnections > 20) {
+ /* if we use many (whatever this means, 20 is randomly picked)
+ * connections, we need to make sure we have a high enough
+ * limit. -- rgerhards, 2010-03-25
+ */
+ struct rlimit maxFiles;
+ maxFiles.rlim_cur = numConnections + 20;
+ maxFiles.rlim_max = numConnections + 20;
+ if(setrlimit(RLIMIT_NOFILE, &maxFiles) < 0) {
+ perror("setrlimit to increase file handles failed");
+ exit(1);
+ }
+ }
+
+ if(dataFile != NULL) {
+ if((dataFP = fopen(dataFile, "r")) == NULL) {
+ perror(dataFile);
+ exit(1);
+ }
+ }
+
if(openConnections() != 0) {
printf("error opening connections\n");
exit(1);
diff --git a/tests/testsuites/random.conf b/tests/testsuites/random.conf
new file mode 100644
index 00000000..a7079df1
--- /dev/null
+++ b/tests/testsuites/random.conf
@@ -0,0 +1,13 @@
+# we write to /dev/null, as we have no chance to verify the output
+# in any case. What we really check is that rsyslogd does not
+# segfault or otherwise abort.
+# rgerhards, 2010-04-01
+$IncludeConfig diag-common.conf
+
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$MainMsgQueueTimeoutShutdown 10000
+$InputTCPServerRun 13514
+
+$template outfmt,"%rawmsg%\n"
+$template dynfile,"rsyslog.out.log" # trick to use relative path names!
+*.* /dev/null
diff --git a/tests/testsuites/samples.snare_ccoff_udp2 b/tests/testsuites/samples.snare_ccoff_udp2
index 7837b820..337cd97c 100644
--- a/tests/testsuites/samples.snare_ccoff_udp2
+++ b/tests/testsuites/samples.snare_ccoff_udp2
@@ -9,14 +9,18 @@
# to be adapted. We do NOT try to preserve misbehaviour on such seriously malformed
# messages.
#
+# this is a very simple test, though not snare-based
+test
+insert into windows (Message, Facility,FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('', 1, 'test',5, '20100321185328', '20100321185328', 1, '')
+# and yet another one we have seen in practice
+UX=Abcd-efg-hij-klmno; XXXXX=1111111111, Z123=192.12.231.245:11111, S1234=123456789, XXXXXX=111111111
+insert into windows (Message, Facility,FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values (' XXXXX=1111111111, Z123=192.12.231.245:11111, S1234=123456789, XXXXXX=111111111', 1, 'localhost',5, '20100321185328', '20100321185328', 1, 'UX=Abcd-efg-hij-klmno;')
# Sample 1 - note the absence of PRI!
windowsserver MSWinEventLog 1 Security 1167 Fri Mar 19 15:33:30 2010 540 Security SYSTEM User Success Audit WINDOWSSERVER Logon/Logoff Successful Network Logon: User Name: WINDOWSSERVER$ Domain: DOMX Logon ID: (0x0,0xF88396) Logon Type: 3 Logon Process: Kerberos Authentication Package: Kerberos Workstation Name: Logon GUID: {79b6eb79-7bcc-8a2e-7dad-953c51dc00fd} Caller User Name: - Caller Domain: - Caller Logon ID: - Caller Process ID: - Transited Services: - Source Network Address: 10.11.11.3 Source Port: 3306 733\n
-insert into windows (Message, Facility,FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values (' Mar 19 15:33:30 2010 540 Security SYSTEM User Success Audit WINDOWSSERVER Logon/Logoff Successful Network Logon: User Name: WINDOWSSERVER$ Domain: DOMX Logon ID: (0x0,0xF88396) Logon Type: 3 Logon Process: Kerberos Authentication Package: Kerberos Workstation Name: Logon GUID: {79b6eb79-7bcc-8a2e-7dad-953c51dc00fd} Caller User Name: - Caller Domain: - Caller Logon ID: - Caller Process ID: - Transited Services: - Source Network Address: 10.11.11.3 Source Port: 3306 733 ', 1, 'localhost',5, '20100321185328', '20100321185328', 1, 'windowsserver MSWinEventLog 1 Security 1167 Fri')
+insert into windows (Message, Facility,FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values (' Mar 19 15:33:30 2010 540 Security SYSTEM User Success Audit WINDOWSSERVER Logon/Logoff Successful Network Logon: User Name: WINDOWSSERVER$ Domain: DOMX Logon ID: (0x0,0xF88396) Logon Type: 3 Logon Process: Kerberos Authentication Package: Kerberos Workstation Name: Logon GUID: {79b6eb79-7bcc-8a2e-7dad-953c51dc00fd} Caller User Name: - Caller Domain: - Caller Logon ID: - Caller Process ID: - Transited Services: - Source Network Address: 10.11.11.3 Source Port: 3306 733', 1, 'localhost',5, '20100321185328', '20100321185328', 1, 'windowsserver MSWinEventLog 1 Security 1167 Fri')
# Sample 2
-# the samples below need to be disabled for the "workaround patch" for the message
-# parser to work. They need to be re-enabled once a final solution has been crafted
-#windowsserver MSWinEventLog 1 Security 1166 Fri Mar 19 15:33:30 2010 576 Security SYSTEM User Success Audit WINDOWSSERVER Logon/Logoff Special privileges assigned to new logon: User Name: WINDOWSSERVER$ Domain: DOMX Logon ID: (0x0,0xF88396) Privileges: SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeEnableDelegationPrivilege 732\n
-#insert into windows (Message, Facility,FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values (' Mar 19 15:33:30 2010 576 Security SYSTEM User Success Audit WINDOWSSERVER Logon/Logoff Special privileges assigned to new logon: User Name: WINDOWSSERVER$ Domain: DOMX Logon ID: (0x0,0xF88396) Privileges: SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeEnableDelegationPrivilege 732', 1, 'localhost',5, '20100321185328', '20100321185328', 1, 'windowsserver MSWinEventLog 1 Security 1166 Fri')
+windowsserver MSWinEventLog 1 Security 1166 Fri Mar 19 15:33:30 2010 576 Security SYSTEM User Success Audit WINDOWSSERVER Logon/Logoff Special privileges assigned to new logon: User Name: WINDOWSSERVER$ Domain: DOMX Logon ID: (0x0,0xF88396) Privileges: SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeEnableDelegationPrivilege 732\n
+insert into windows (Message, Facility,FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values (' Mar 19 15:33:30 2010 576 Security SYSTEM User Success Audit WINDOWSSERVER Logon/Logoff Special privileges assigned to new logon: User Name: WINDOWSSERVER$ Domain: DOMX Logon ID: (0x0,0xF88396) Privileges: SeSecurityPrivilege SeBackupPrivilege SeRestorePrivilege SeTakeOwnershipPrivilege SeDebugPrivilege SeSystemEnvironmentPrivilege SeLoadDriverPrivilege SeImpersonatePrivilege SeEnableDelegationPrivilege 732', 1, 'localhost',5, '20100321185328', '20100321185328', 1, 'windowsserver MSWinEventLog 1 Security 1166 Fri')
# Sample 3
-#windowsserver MSWinEventLog 1 Security 1165 Fri Mar 19 15:33:30 2010 538 Security SYSTEM User Success Audit WINDOWSSERVER Logon/Logoff User Logoff: User Name: WINDOWSSERVER$ Domain: DOMX Logon ID: (0x0,0xF8830B) Logon Type: 3 731\n
-#insert into windows (Message, Facility,FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values (' Mar 19 15:33:30 2010 538 Security SYSTEM User Success Audit WINDOWSSERVER Logon/Logoff User Logoff: User Name: WINDOWSSERVER$ Domain: DOMX Logon ID: (0x0,0xF8830B) Logon Type: 3 731', 1, 'localhost',5, '20100321185328', '20100321185328', 1, 'windowsserver MSWinEventLog 1 Security 1165 Fri')
+windowsserver MSWinEventLog 1 Security 1165 Fri Mar 19 15:33:30 2010 538 Security SYSTEM User Success Audit WINDOWSSERVER Logon/Logoff User Logoff: User Name: WINDOWSSERVER$ Domain: DOMX Logon ID: (0x0,0xF8830B) Logon Type: 3 731\n
+insert into windows (Message, Facility,FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values (' Mar 19 15:33:30 2010 538 Security SYSTEM User Success Audit WINDOWSSERVER Logon/Logoff User Logoff: User Name: WINDOWSSERVER$ Domain: DOMX Logon ID: (0x0,0xF8830B) Logon Type: 3 731', 1, 'localhost',5, '20100321185328', '20100321185328', 1, 'windowsserver MSWinEventLog 1 Security 1165 Fri')
diff --git a/tools/omfile.c b/tools/omfile.c
index 1ade3132..d9dce4f9 100644
--- a/tools/omfile.c
+++ b/tools/omfile.c
@@ -109,6 +109,7 @@ typedef struct s_dynaFileCacheEntry dynaFileCacheEntry;
#define IOBUF_DFLT_SIZE 1024 /* default size for io buffers */
#define FLUSH_INTRVL_DFLT 1 /* default buffer flush interval (in seconds) */
#define USE_ASYNCWRITER_DFLT 0 /* default buffer use async writer */
+#define FLUSHONTX_DFLT 1 /* default for flush on TX end */
#define DFLT_bForceChown 0
/* globals for default values */
@@ -124,7 +125,7 @@ static uid_t dirGID; /* GID to be used for newly created directories */
static int bCreateDirs = 1;/* auto-create directories for dynaFiles: 0 - no, 1 - yes */
static int bEnableSync = 0;/* enable syncing of files (no dash in front of pathname in conf): 0 - no, 1 - yes */
static int iZipLevel = 0; /* zip compression mode (0..9 as usual) */
-static bool bFlushOnTXEnd = 0;/* flush write buffers when transaction has ended? */
+static bool bFlushOnTXEnd = FLUSHONTX_DFLT;/* flush write buffers when transaction has ended? */
static int64 iIOBufSize = IOBUF_DFLT_SIZE; /* size of an io buffer */
static int iFlushInterval = FLUSH_INTRVL_DFLT; /* how often flush the output buffer on inactivity? */
static int bUseAsyncWriter = USE_ASYNCWRITER_DFLT; /* should we enable asynchronous writing? */
@@ -822,7 +823,7 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
bCreateDirs = 1;
bEnableSync = 0;
iZipLevel = 0;
- bFlushOnTXEnd = 0;
+ bFlushOnTXEnd = FLUSHONTX_DFLT;
iIOBufSize = IOBUF_DFLT_SIZE;
iFlushInterval = FLUSH_INTRVL_DFLT;
bUseAsyncWriter = USE_ASYNCWRITER_DFLT;
diff --git a/tools/ompipe.c b/tools/ompipe.c
index 5fb9b27e..7cf61822 100644
--- a/tools/ompipe.c
+++ b/tools/ompipe.c
@@ -39,6 +39,7 @@
#include <string.h>
#include <assert.h>
#include <errno.h>
+#include <fcntl.h>
#include <sys/file.h>
#include "syslogd.h"
diff --git a/tools/syslogd.c b/tools/syslogd.c
index 887ffbd2..9900bfb1 100644
--- a/tools/syslogd.c
+++ b/tools/syslogd.c
@@ -2395,6 +2395,7 @@ int realMain(int argc, char **argv)
uchar *LocalHostName;
uchar *LocalDomain;
uchar *LocalFQDNName;
+ char cwdbuf[128]; /* buffer to obtain/display current working directory */
/* 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
@@ -2481,8 +2482,9 @@ int realMain(int argc, char **argv)
if ((argc -= optind))
usage();
- DBGPRINTF("rsyslogd %s startup, compatibility mode %d, module path '%s'\n",
- VERSION, iCompatibilityMode, glblModPath == NULL ? "" : (char*)glblModPath);
+ DBGPRINTF("rsyslogd %s startup, compatibility mode %d, module path '%s', cwd:%s\n",
+ VERSION, iCompatibilityMode, glblModPath == NULL ? "" : (char*)glblModPath,
+ getcwd(cwdbuf, sizeof(cwdbuf)));
/* we are done with the initial option parsing and processing. Now we init the system. */