summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog35
-rw-r--r--Makefile.am4
-rw-r--r--configure.ac38
-rw-r--r--dirty.h1
-rw-r--r--doc/expression.html21
-rw-r--r--doc/imuxsock.html28
-rw-r--r--doc/manual.html2
-rw-r--r--doc/omoracle.html11
-rw-r--r--doc/rainerscript.html18
-rw-r--r--doc/rsconf1_omfileforcechown.html64
-rw-r--r--doc/rsyslog_conf_global.html6
-rw-r--r--gss-misc.c25
-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/imgssapi/imgssapi.c16
-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/imudp/imudp.c20
-rw-r--r--plugins/imuxsock/imuxsock.c47
-rw-r--r--plugins/omoracle/omoracle.c64
-rw-r--r--runtime/Makefile.am2
-rw-r--r--runtime/atomic-posix-sem.c70
-rw-r--r--runtime/atomic.h120
-rw-r--r--runtime/cfsysline.c8
-rw-r--r--runtime/debug.c4
-rw-r--r--runtime/debug.h5
-rw-r--r--runtime/glbl.c12
-rw-r--r--runtime/glbl.h11
-rw-r--r--runtime/nsdsel_ptcp.c51
-rw-r--r--runtime/nsdsel_ptcp.h5
-rw-r--r--runtime/rsyslog.c14
-rw-r--r--runtime/unlimited_select.h45
-rw-r--r--runtime/vm.c44
-rw-r--r--solaris/README38
-rw-r--r--solaris/cddllicense.txt242
-rw-r--r--tests/Makefile.am6
-rwxr-xr-xtests/complex1.sh5
-rwxr-xr-xtests/diag.sh15
-rw-r--r--tests/msleep.c50
-rw-r--r--tests/nettester.c83
-rwxr-xr-xtests/rsf_getenv.sh17
-rw-r--r--tests/rt-init.c2
-rw-r--r--tests/tcpflood.c15
-rw-r--r--tests/testsuites/rsf_getenv.conf17
-rw-r--r--tools/omfile.c26
-rw-r--r--tools/ompipe.c1
-rw-r--r--tools/syslogd.c58
50 files changed, 2774 insertions, 129 deletions
diff --git a/ChangeLog b/ChangeLog
index 3c77751a..8fc06ec0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,33 @@
---------------------------------------------------------------------------
+Version 4.7.0 [v4-devel] (rgerhards), 2009-09-??
+- new: support for Solaris added (but not yet the Solaris door API)
+- added function getenv() to RainerScript
+- added new config option $InputUnixListenSocketCreatePath
+ to permit the auto-creation of pathes to additional log sockets. This
+ turns out to be useful if they reside on temporary file systems and
+ rsyslogd starts up before the daemons that create these sockets
+ (rsyslogd always creates the socket itself if it does not exist).
+- added $LogRSyslogStatusMessages configuration directive
+ permitting to turn off rsyslog start/stop/HUP messages. See Debian
+ ticket http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=463793
+- added new config directive $omfileForceChown to (try to) fix some broken
+ system configs.
+ See ticket for details: http://bugzilla.adiscon.com/show_bug.cgi?id=150
+- added $EscapeControlCharacterTab config directive
+ Thanks to Jonathan Bond-Caron for the patch.
+- added option to use unlimited-size select() calls
+ Thanks to varmjofekoj for the patch
+- debugondemand mode caused backgrounding to fail - close to a bug, but I'd
+ consider the ability to background in this mode a new feature...
+- bugfix (kind of): check if TCP connection is still alive if using TLS
+ Thanks to Jonathan Bond-Caron for the patch.
+- imported changes from 4.5.7 and below
+- bugfix: potential segfault when -p command line option was used
+ Thanks for varmojfekoj for pointing me at this bug.
+- bugfix: potential segfaults during queue shutdown
+ (bugs require certain non-standard settings to appear)
+ Thanks to varmojfekoj for the patch [imported from 4.5.8]
+---------------------------------------------------------------------------
Version 4.6.3 [v4-stable] (rgerhards), 2010-04-??
- improvded testbench
- added test with truly random data received via syslog to test
@@ -16,10 +45,16 @@ Version 4.6.3 [v4-stable] (rgerhards), 2010-04-??
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 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 f5f9a6ed..a02fa6a2 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 bfd78281..a6ac2abc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
-AC_INIT([rsyslog],[4.6.2],[rsyslog@lists.adiscon.com])
+AC_INIT([rsyslog],[4.7.0],[rsyslog@lists.adiscon.com])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([ChangeLog])
AC_CONFIG_MACRO_DIR([m4])
@@ -84,6 +84,7 @@ AC_TYPE_UINT8_T
AC_HEADER_TIME
AC_STRUCT_TM
AC_C_VOLATILE
+AC_C_TYPEOF
sa_includes="\
$ac_includes_default
@@ -126,6 +127,9 @@ AC_TRY_COMPILE([
# check for availability of atomic operations
RS_ATOMIC_OPERATIONS
+# fall back to POSIX sems for atomic operations (cpu expensive)
+AC_CHECK_HEADERS([semaphore.h])
+
# Additional module directories
AC_ARG_WITH(moddirs,
@@ -274,6 +278,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)
#
@@ -335,6 +340,21 @@ AC_ARG_ENABLE([fsstnd],
])
+# support for unlimited select() syscall
+AC_ARG_ENABLE(unlimited_select,
+ [AS_HELP_STRING([--enable-unlimited-select],[Enable unlimited select() syscall @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_unlimited_select="yes" ;;
+ no) enable_unlimited_select="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-unlimited-select) ;;
+ esac],
+ [enable_unlimited_select="no"]
+)
+if test "$enable_unlimited_select" = "yes"; then
+ AC_DEFINE(USE_UNLIMITED_SELECT, 1, [If defined, the select() syscall won't be limited to a particular number of file descriptors.])
+fi
+
+
# debug
AC_ARG_ENABLE(debug,
[AS_HELP_STRING([--enable-debug],[Enable debug mode @<:@default=no@:>@])],
@@ -727,6 +747,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@:>@])],
@@ -828,6 +861,7 @@ AC_CONFIG_FILES([Makefile \
plugins/omprog/Makefile \
plugins/omstdout/Makefile \
plugins/imfile/Makefile \
+ plugins/imdoor/Makefile \
plugins/imrelp/Makefile \
plugins/imdiag/Makefile \
plugins/omtesting/Makefile \
@@ -854,11 +888,13 @@ echo " Zlib compression support enabled: $enable_zlib"
echo " rsyslog runtime will be built: $enable_rsyslogrt"
echo " rsyslogd will be built: $enable_rsyslogd"
echo " custom module 1 will be built: $enable_cust1"
+echo " Unlimited select() support enabled: $enable_unlimited_select"
echo
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/dirty.h b/dirty.h
index 0153cb69..f1904574 100644
--- a/dirty.h
+++ b/dirty.h
@@ -54,6 +54,7 @@ extern int bReduceRepeatMsgs;
extern int bDropTrailingLF;
extern uchar cCCEscapeChar;
extern int bEscapeCCOnRcv;
+extern int bEscapeTab;
#ifdef USE_NETZIP
/* config param: minimum message size to try compression. The smaller
* the message, the less likely is any compression gain. We check for
diff --git a/doc/expression.html b/doc/expression.html
index 9e37cb7a..c401d9ab 100644
--- a/doc/expression.html
+++ b/doc/expression.html
@@ -1,17 +1,22 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>
-<meta http-equiv="Content-Language" content="en"><title>Expressions</title></head>
+<meta http-equiv="Content-Language" content="en">
+<title>Expressions in rsyslog</title></head>
<body>
-<a href="rsyslog_conf_filter.html">back</a>
-<h1>Expressions</h1>
+<a href="rsyslog_conf_filter.html">back to rsyslog filter conditions</a>
+<h1>Expressions in rsyslog</h1>
<p>Rsyslog supports expressions at a growing number of places. So
-far, they are supported for filtering messages.</p><p>Expression support is provided by RainerScript. For now, please see the formal expression definition in <a href="rainerscript.html">RainerScript ABNF</a>. It is the "expr" node.</p><p>C-like comments (/* some comment */) are supported <span style="font-weight: bold;">inside</span> the expression, but not yet in the rest of the configuration file.</p><p>[<a href="rsyslog_conf.html">rsyslog.conf overview</a>]
+far, they are supported for filtering messages.</p>
+<p>Expression support is provided by RainerScript. Please see the
+<a href="rainerscript.html">RainerScript documentation</a> for more details.</p>
+<p>C-like comments (/* some comment */) are supported <b>inside</b> the expression,
+but not yet in the rest of the configuration file.</p>
+
+<p>[<a href="rsyslog_conf.html">rsyslog.conf overview</a>]
[<a href="manual.html">manual index</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p>
<p><font size="2">This documentation is part of the
-<a href="http://www.rsyslog.com/">rsyslog</a>
-project.<br>
-Copyright © 2008 by <a href="http://www.gerhards.net/rainer">Rainer
-Gerhards</a> and
+<a href="http://www.rsyslog.com/">rsyslog</a> project.<br>
+Copyright &copy; 2008, 2009 by <a href="http://www.gerhards.net/rainer">Rainer Gerhards</a> and
<a href="http://www.adiscon.com/">Adiscon</a>.
Released under the GNU GPL version 3 or higher.</font></p>
</body></html>
diff --git a/doc/imuxsock.html b/doc/imuxsock.html
index 472470a0..15c365a6 100644
--- a/doc/imuxsock.html
+++ b/doc/imuxsock.html
@@ -46,6 +46,18 @@ Ignore timestamps included in the messages, applies to messages received via the
<li><b>$SystemLogSocketName</b> &lt;name-of-socket&gt; -- former -p option</li>
<li><b>$SystemLogFlowControl</b> [on/<b>off</b>] - specifies if flow control should be applied
to the system log socket.</li>
+<li><b>$InputUnixListenSocketCreatePath</b> [on/<b>off</b>] - create directories in the socket path
+if they do not already exist. They are created with 0755 permissions with the owner being the process under
+which rsyslogd runs. The default is not to create directories. Keep in mind, though, that rsyslogd always
+creates the socket itself if it does not exist (just not the directories by default).
+<br>Note that this statement affects the
+next $AddUnixListenSocket directive that follows in sequence in the configuration file. It never works
+on the system log socket (where it is deemed unnecessary). Also note that it is automatically
+being reset to &quot;off&quot; after the $AddUnixListenSocket directive, so if you would have it active
+for two additional listen sockets, you need to specify it in front of each one. This option is primarily considered
+useful for defining additional sockets that reside on non-permanent file systems. As rsyslogd probably starts
+up before the daemons that create these sockets, it is a vehicle to enable rsyslogd to listen to those
+sockets even though their directories do not yet exist. [available since 4.7.0 and 5.3.0]</li>
<li><b>$AddUnixListenSocket</b> &lt;name-of-socket&gt; adds additional unix socket, default none -- former -a option</li>
<li><b>$InputUnixListenSocketHostName</b> &lt;hostname&gt; permits to override the hostname that
shall be used inside messages taken from the <b>next</b> $AddUnixListenSocket socket. Note that
@@ -57,20 +69,32 @@ that the local hostname can be overridden in cases where that is desired.</li>
<br>
This documentation is sparse and incomplete.
<p><b>Sample:</b></p>
-<p>The following sample is the minimum setup required to accept syslog messages from applications running on the local system.<br>
+<p>The following sample is the minimum setup required to accept syslog messages from applications running
+on the local system.<br>
</p>
<textarea rows="2" cols="70">$ModLoad imuxsock # needs to be done just once
$SystemLogSocketFlowControl on # enable flow control (use if needed)
</textarea>
<p>The following sample is a configuration where rsyslogd pulls logs from two
jails, and assigns different hostnames to each of the jails: </p>
-<textarea rows="6" cols="60">$ModLoad imuxsock # needs to be done just once
+<textarea rows="6" cols="70">$ModLoad imuxsock # needs to be done just once
$InputUnixListenSocketHostName jail1.example.net
$AddUnixListenSocket /jail/1/dev/log
$InputUnixListenSocketHostName jail2.example.net
$AddUnixListenSocket /jail/2/dev/log
</textarea>
+<p>The following sample is a configuration where rsyslogd reads the openssh log
+messages via a separate socket, but this socket is created on a temporary file
+system. As rsyslogd starts up before the sshd, it needs to create the socket
+directories, because it otherwise can not open the socket and thus not listen
+to openssh messages. Note that it is vital not to place any other socket between
+the $InputUnixListenSocketCreatePath and the $InputUnixListenSocketHostName.</p>
+<textarea rows="6" cols="70">$ModLoad imuxsock # needs to be done just once
+
+$InputUnixListenSocketCreatePath on # turn on for *next* socket
+$InputUnixListenSocketHostName /var/run/sshd/dev/log
+</textarea>
<p>[<a href="rsyslog_conf.html">rsyslog.conf overview</a>]
[<a href="manual.html">manual index</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p>
<p><font size="2">This documentation is part of the
diff --git a/doc/manual.html b/doc/manual.html
index 455a7116..3d9a2f2d 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -19,7 +19,7 @@ rsyslog support</a> available directly from the source!</p>
<p><b>Please visit the <a href="http://www.rsyslog.com/sponsors">rsyslog sponsor's page</a>
to honor the project sponsors or become one yourself!</b> We are very grateful for any help towards the
project goals.</p>
-<p><b>This documentation is for version 4.6.2 (v4-stable branch) of rsyslog.</b>
+<p><b>This documentation is for version 4.7.0 (v4-devel branch) of rsyslog.</b>
Visit the <i><a href="http://www.rsyslog.com/doc-status.html">rsyslog status page</a></i></b>
to obtain current version information and project status.
</p><p><b>If you like rsyslog, you might
diff --git a/doc/omoracle.html b/doc/omoracle.html
index cfcf277f..2bb6aa5d 100644
--- a/doc/omoracle.html
+++ b/doc/omoracle.html
@@ -13,10 +13,11 @@
<p><b>Available since: </b>: 4.3.0
<p><b>Status: </b>: contributed module, not maitained by rsyslog core authors
<p><b>Description</b>:</p>
-<p>This module provides native support for logging to Oracle databases. It offers
-superior performance over the more generic <a href="omlibdbi.html">omlibdbi</a> module.
-It also includes a number of enhancements, most importantly prepared statements and
-batching, what provides a big performance improvements.
+<p>This module provides native support for logging to Oracle
+databases. It offers superior performance over the more
+generic <a href="omlibdbi.html">omlibdbi</a> module. It also includes
+a number of enhancements, most importantly prepared statements and
+batching, what provides a big performance improvement.
</p>
<p>Note that this module is maintained by its original author. If you need assistance with it,
it is suggested to post questions to the
@@ -63,7 +64,7 @@ it is suggested to post questions to the
$OmoracleStatement \
insert into foo(hostname,message)values(:host,:message)
- Also note that identifiers to placeholders are arbitrarry. You
+ Also note that identifiers to placeholders are arbitrary. You
need to define the properties on the template in the correct order
you want them passed to the statement!
</pre>
diff --git a/doc/rainerscript.html b/doc/rainerscript.html
index ef0e41cb..63a79040 100644
--- a/doc/rainerscript.html
+++ b/doc/rainerscript.html
@@ -51,13 +51,25 @@ of a and b should be tested as "a &lt;&gt; b". The "not" operator
should be reserved to cases where it actually is needed to form a
complex boolean expression. In those cases, parenthesis are highly
recommended.
+<h2>Functions</h2>
+<p>RainerScript supports a currently quite limited set of functions:
+<ul>
+<li>getenv(str) - like the OS call, returns the value of the environment
+variable, if it exists. Returns an empty string if it does not exist.
+<li>strlen(str) - returns the length of the provided string
+<li>tolower(str) - converts the provided string into lowercase
+</ul>
+<p>The following example can be used to build a dynamic filter based on some environment
+variable:
+<pre>
+if $msg contains getenv('TRIGGERVAR') then /path/to/errfile
+</pre>
<p>[<a href="rsyslog_conf.html">rsyslog.conf overview</a>]
[<a href="manual.html">manual index</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p>
<p><font size="2">This documentation is part of the
<a href="http://www.rsyslog.com/">rsyslog</a>
project.<br>
-Copyright © 2008 by <a href="http://www.gerhards.net/rainer">Rainer
-Gerhards</a> and
+Copyright &copy; 2008, 2009 by <a href="http://www.gerhards.net/rainer">Rainer Gerhards</a> and
<a href="http://www.adiscon.com/">Adiscon</a>.
Released under the GNU GPL version 3 or higher.</font></p>
-</body></html> \ No newline at end of file
+</body></html>
diff --git a/doc/rsconf1_omfileforcechown.html b/doc/rsconf1_omfileforcechown.html
new file mode 100644
index 00000000..7415a6f6
--- /dev/null
+++ b/doc/rsconf1_omfileforcechown.html
@@ -0,0 +1,64 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<a href="rsyslog_conf_global.html">back</a>
+
+<h2>$omfileForceChown</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Parameter Values:</b> boolean (on/off, yes/no)</p>
+<p><b>Available since:</b> 4.7.0+, 5.3.0+</p>
+<p><b>Default:</b> off</p>
+<p><b>Description:</b></p>
+<p>Forces rsyslogd to change the ownership for output files that already exist. Please note
+that this tries to fix a potential problem that exists outside the scope of rsyslog. Actually,
+it tries to fix invalid ownership/permission settings set by the original file creator.
+<p>Rsyslog changes the ownership during initial execution with root privileges. When a privelege
+drop is configured, privileges are dropped after the file owner ship is changed. Not that this currently
+is a limitation in rsyslog's privilege drop code, which is on the TODO list to be removed. See Caveats
+section below for the important implications.
+<p><b>Caveats:</b></p>
+<p>This directive tries to fix a problem that actually is outside the scope of rsyslog. As such,
+there are a couple of restrictions and situations in which it will not work. <b>Users are strongly
+encouraged to fix their system instead of turning this directive on</b> - it should only be used
+as a last resort.
+<p>At least in the following scenario, this directive will fail expectedly:
+<p>It does not address
+the situation that someone changes the ownership *after* rsyslogd has started.
+Let's, for example, consider a log rotation script.
+<ul>
+<li>rsyslog is started
+<li>ownership is changed
+<li>privileges dropped
+<li>log rotation (lr) script starts
+<li>lr removes files
+<li>lr creates new files with root:adm (or whatever else)
+<li>lr HUPs rsyslogd
+<li>rsyslogd closes files
+<li>rsyslogd tries to open files
+<li>rsyslogd tries to change ownership --&gt; fail as we are non-root now
+<li>file open fails
+</ul>
+
+Please note that once the privilege drop code is refactored, this directive will
+no longer work, because then privileges will be dropped before any action is performed,
+and thus we will no longer be able to chown files that do not belong to the
+user rsyslogd is configured to run under.
+
+<p>So <b>expect the directive to go away</b>. It will not
+be removed in version 4, but may disappear at any time for any version greater than 4.
+
+<p><b>Sample:</b></p>
+<p><code><b>$FileOwner loguser</b>
+<br><b>$omfileForceChown on</b></code></p>
+
+<p>[<a href="rsyslog_conf.html">rsyslog.conf overview</a>] [<a href="manual.html">manual
+index</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p>
+<p><font size="2">This documentation is part of the
+<a href="http://www.rsyslog.com/">rsyslog</a> project.<br>
+Copyright &copy; 2007 by <a href="http://www.gerhards.net/rainer">Rainer Gerhards</a> and
+<a href="http://www.adiscon.com/">Adiscon</a>. Released under the GNU GPL
+version 2 or higher.</font></p>
+</body>
+</html>
diff --git a/doc/rsyslog_conf_global.html b/doc/rsyslog_conf_global.html
index ce46bac2..8137bcba 100644
--- a/doc/rsyslog_conf_global.html
+++ b/doc/rsyslog_conf_global.html
@@ -130,6 +130,7 @@ our paper on <a href="multi_ruleset.html">using multiple rule sets in rsyslog</a
<li><a href="rsconf1_droptrailinglfonreception.html">$DropTrailingLFOnReception</a></li>
<li><a href="rsconf1_dynafilecachesize.html">$DynaFileCacheSize</a></li>
<li><a href="rsconf1_escapecontrolcharactersonreceive.html">$EscapeControlCharactersOnReceive</a></li>
+<li><b>$EscapeControlCharactersOnReceive</b> [<b>on</b>|off] - escape USASCII HT character</li>
<li>$ErrorMessagesToStderr [<b>on</b>|off] - direct rsyslogd error message to stderr (in addition to other targets)</li>
<li><a href="rsconf1_failonchownfailure.html">$FailOnChownFailure</a></li>
<li><a href="rsconf1_filecreatemode.html">$FileCreateMode</a></li>
@@ -149,6 +150,10 @@ Usually that should not be a big issue, as the restart-type HUP can easily be re
something along the lines of &quot;/etc/init.d/rsyslog restart&quot;.
</li>
<li><a href="rsconf1_includeconfig.html">$IncludeConfig</a></li><li>MainMsgQueueCheckpointInterval &lt;number&gt;</li>
+<li><b>$LogRSyslogStatusMessages</b> [<b>on</b>/off] - If set to on (the default),
+rsyslog emits message on startup and shutdown as well as when it is HUPed.
+This information might be needed by some log analyzers. If set to off, no such
+status messages are logged, what may be useful for other scenarios.
<li>$MainMsgQueueDequeueSlowdown &lt;number&gt; [number
is timeout in <i> micro</i>seconds (1000000us is 1sec!),
default 0 (no delay). Simple rate-limiting!]</li>
@@ -229,6 +234,7 @@ error recovery thus can handle write errors without data loss. Note that this op
severely reduces the effect of zip compression and should be switched to off
for that use case. Note that the default -on- is primarily an aid to preserve
the traditional syslogd behaviour.</li>
+<li><a href="rsconf1_omfileforcechown.html">$omfileForceChown</a> - force ownership change for all files</li>
<li><b>$RepeatedMsgContainsOriginalMsg</b> [on/<b>off</b>] - "last message repeated n times" messages, if generated,
have a different format that contains the message that is being repeated.
Note that only the first "n" characters are included, with n to be at least 80 characters, most
diff --git a/gss-misc.c b/gss-misc.c
index c9220595..978454ff 100644
--- a/gss-misc.c
+++ b/gss-misc.c
@@ -51,11 +51,14 @@
#include "obj.h"
#include "errmsg.h"
#include "gss-misc.h"
+#include "glbl.h"
+#include "unlimited_select.h"
MODULE_TYPE_LIB
/* static data */
DEFobjStaticHelpers
+DEFobjCurrIf(glbl)
DEFobjCurrIf(errmsg)
static void display_status_(char *m, OM_uint32 code, int type)
@@ -108,28 +111,38 @@ static int read_all(int fd, char *buf, unsigned int nbyte)
{
int ret;
char *ptr;
- fd_set rfds;
struct timeval tv;
+#ifdef USE_UNLIMITED_SELECT
+ fd_set *pRfds = malloc(glbl.GetFdSetSize());
+#else
+ fd_set rfds;
+ fd_set *pRfds = &rfds;
+#endif
for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) {
- FD_ZERO(&rfds);
- FD_SET(fd, &rfds);
+ FD_ZERO(pRfds);
+ FD_SET(fd, pRfds);
tv.tv_sec = 1;
tv.tv_usec = 0;
- if ((ret = select(FD_SETSIZE, &rfds, NULL, NULL, &tv)) <= 0
- || !FD_ISSET(fd, &rfds))
+ if ((ret = select(FD_SETSIZE, pRfds, NULL, NULL, &tv)) <= 0
+ || !FD_ISSET(fd, pRfds)) {
+ freeFdSet(pRfds);
return ret;
+ }
ret = recv(fd, ptr, nbyte, 0);
if (ret < 0) {
if (errno == EINTR)
continue;
+ freeFdSet(pRfds);
return (ret);
} else if (ret == 0) {
+ freeFdSet(pRfds);
return (ptr - buf);
}
}
+ freeFdSet(pRfds);
return (ptr - buf);
}
@@ -264,6 +277,7 @@ BEGINObjClassExit(gssutil, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END M
CODESTARTObjClassExit(gssutil)
/* release objects we no longer need */
objRelease(errmsg, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
ENDObjClassExit(gssutil)
@@ -274,6 +288,7 @@ ENDObjClassExit(gssutil)
BEGINAbstractObjClassInit(gssutil, 1, OBJ_IS_LOADABLE_MODULE) /* class, version - CHANGE class also in END MACRO! */
/* request objects we use */
CHKiRet(objUse(errmsg, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
ENDObjClassInit(gssutil)
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/imgssapi/imgssapi.c b/plugins/imgssapi/imgssapi.c
index d8791880..1aad6622 100644
--- a/plugins/imgssapi/imgssapi.c
+++ b/plugins/imgssapi/imgssapi.c
@@ -56,6 +56,7 @@
#include "errmsg.h"
#include "netstrm.h"
#include "glbl.h"
+#include "unlimited_select.h"
MODULE_TYPE_INPUT
@@ -414,15 +415,20 @@ OnSessAcceptGSS(tcpsrv_t *pThis, tcps_sess_t *pSess)
CHKiRet(netstrm.GetSock(pSess->pStrm, &fdSess)); // TODO: method access!
if (allowedMethods & ALLOWEDMETHOD_TCP) {
int len;
- fd_set fds;
struct timeval tv;
+#ifdef USE_UNLIMITED_SELECT
+ fd_set *pFds = malloc(glbl.GetFdSetSize());
+#else
+ fd_set fds;
+ fd_set *pFds = &fds;
+#endif
do {
- FD_ZERO(&fds);
- FD_SET(fdSess, &fds);
+ FD_ZERO(pFds);
+ FD_SET(fdSess, pFds);
tv.tv_sec = 1;
tv.tv_usec = 0;
- ret = select(fdSess + 1, &fds, NULL, NULL, &tv);
+ ret = select(fdSess + 1, pFds, NULL, NULL, &tv);
} while (ret < 0 && errno == EINTR);
if (ret < 0) {
errmsg.LogError(0, RS_RET_ERR, "TCP session %p will be closed, error ignored\n", pSess);
@@ -475,6 +481,8 @@ OnSessAcceptGSS(tcpsrv_t *pThis, tcps_sess_t *pSess)
pGSess->allowedMethods = ALLOWEDMETHOD_TCP;
ABORT_FINALIZE(RS_RET_OK); // TODO: define good error codes
}
+
+ freeFdSet(pFds);
}
context = &pGSess->gss_context;
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/imudp/imudp.c b/plugins/imudp/imudp.c
index f8555f00..d76f3544 100644
--- a/plugins/imudp/imudp.c
+++ b/plugins/imudp/imudp.c
@@ -45,6 +45,7 @@
#include "datetime.h"
#include "prop.h"
#include "unicode-helper.h"
+#include "unlimited_select.h"
MODULE_TYPE_INPUT
@@ -287,12 +288,18 @@ BEGINrunInput
int maxfds;
int nfds;
int i;
- fd_set readfds;
struct sockaddr_storage frominetPrev;
int bIsPermitted;
uchar fromHost[NI_MAXHOST];
uchar fromHostIP[NI_MAXHOST];
uchar fromHostFQDN[NI_MAXHOST];
+#ifdef USE_UNLIMITED_SELECT
+ fd_set *pReadfds = malloc(glbl.GetFdSetSize());
+#else
+ fd_set readfds;
+ fd_set *pReadfds = &readfds;
+#endif
+
CODESTARTrunInput
/* start "name caching" algo by making sure the previous system indicator
* is invalidated.
@@ -311,30 +318,30 @@ CODESTARTrunInput
* is given without -a, we do not need to listen at all..
*/
maxfds = 0;
- FD_ZERO (&readfds);
+ FD_ZERO (pReadfds);
/* Add the UDP listen sockets to the list of read descriptors. */
for (i = 0; i < *udpLstnSocks; i++) {
if (udpLstnSocks[i+1] != -1) {
if(Debug)
net.debugListenInfo(udpLstnSocks[i+1], "UDP");
- FD_SET(udpLstnSocks[i+1], &readfds);
+ FD_SET(udpLstnSocks[i+1], pReadfds);
if(udpLstnSocks[i+1]>maxfds) maxfds=udpLstnSocks[i+1];
}
}
if(Debug) {
dbgprintf("--------imUDP calling select, active file descriptors (max %d): ", maxfds);
for (nfds = 0; nfds <= maxfds; ++nfds)
- if ( FD_ISSET(nfds, &readfds) )
+ if ( FD_ISSET(nfds, pReadfds) )
dbgprintf("%d ", nfds);
dbgprintf("\n");
}
/* wait for io to become ready */
- nfds = select(maxfds+1, (fd_set *) &readfds, NULL, NULL, NULL);
+ nfds = select(maxfds+1, (fd_set *) pReadfds, NULL, NULL, NULL);
for(i = 0; nfds && i < *udpLstnSocks; i++) {
- if(FD_ISSET(udpLstnSocks[i+1], &readfds)) {
+ if(FD_ISSET(udpLstnSocks[i+1], pReadfds)) {
processSocket(udpLstnSocks[i+1], &frominetPrev, &bIsPermitted,
fromHost, fromHostFQDN, fromHostIP);
--nfds; /* indicate we have processed one descriptor */
@@ -343,6 +350,7 @@ CODESTARTrunInput
/* end of a run, back to loop for next recv() */
}
+ freeFdSet(pReadfds);
return iRet;
ENDrunInput
diff --git a/plugins/imuxsock/imuxsock.c b/plugins/imuxsock/imuxsock.c
index 5567a405..daa3bb47 100644
--- a/plugins/imuxsock/imuxsock.c
+++ b/plugins/imuxsock/imuxsock.c
@@ -45,6 +45,7 @@
#include "glbl.h"
#include "msg.h"
#include "prop.h"
+#include "unlimited_select.h"
MODULE_TYPE_INPUT
@@ -77,6 +78,7 @@ static int startIndexUxLocalSockets; /* process funix from that index on (used t
*/
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 int funixCreateSockPath[MAXFUNIX] = { 0, }; /* auto-creation of socket directory? */
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 */
@@ -89,6 +91,8 @@ 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? */
+#define DFLT_bCreateSockPath 0
+static int bCreateSockPath = DFLT_bCreateSockPath; /* auto-create socket path? */
/* set the timestamp ignore / not ignore option for the system
@@ -132,6 +136,7 @@ static rsRetVal addLstnSocketName(void __attribute__((unused)) *pVal, uchar *pNe
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;
+ funixCreateSockPath[nfunix] = bCreateSockPath;
funixn[nfunix++] = pNewVal;
}
else {
@@ -165,7 +170,7 @@ static rsRetVal discardFunixn(void)
}
-static int create_unix_socket(const char *path)
+static int create_unix_socket(const char *path, int bCreatePath)
{
struct sockaddr_un sunx;
int fd;
@@ -177,6 +182,9 @@ static int create_unix_socket(const char *path)
memset(&sunx, 0, sizeof(sunx));
sunx.sun_family = AF_UNIX;
+ if(bCreatePath) {
+ makeFileParentDirs((uchar*)path, strlen(path), 0755, -1, -1, 0);
+ }
(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 ||
@@ -249,7 +257,13 @@ BEGINrunInput
int nfds;
int i;
int fd;
- fd_set readfds;
+#ifdef USE_UNLIMITED_SELECT
+ fd_set *pReadfds = malloc(glbl.GetFdSetSize());
+#else
+ fd_set readfds;
+ fd_set *pReadfds = &readfds;
+#endif
+
CODESTARTrunInput
/* this is an endless loop - it is terminated when the thread is
* signalled to do so. This, however, is handled by the framework,
@@ -263,11 +277,11 @@ CODESTARTrunInput
* is given without -a, we do not need to listen at all..
*/
maxfds = 0;
- FD_ZERO (&readfds);
+ FD_ZERO (pReadfds);
/* Copy master connections */
for (i = startIndexUxLocalSockets; i < nfunix; i++) {
if (funix[i] != -1) {
- FD_SET(funix[i], &readfds);
+ FD_SET(funix[i], pReadfds);
if (funix[i]>maxfds) maxfds=funix[i];
}
}
@@ -275,22 +289,23 @@ CODESTARTrunInput
if(Debug) {
dbgprintf("--------imuxsock calling select, active file descriptors (max %d): ", maxfds);
for (nfds= 0; nfds <= maxfds; ++nfds)
- if ( FD_ISSET(nfds, &readfds) )
+ if ( FD_ISSET(nfds, pReadfds) )
dbgprintf("%d ", nfds);
dbgprintf("\n");
}
/* wait for io to become ready */
- nfds = select(maxfds+1, (fd_set *) &readfds, NULL, NULL, NULL);
+ nfds = select(maxfds+1, (fd_set *) pReadfds, NULL, NULL, NULL);
for (i = 0; i < nfunix && nfds > 0; i++) {
- if ((fd = funix[i]) != -1 && FD_ISSET(fd, &readfds)) {
+ if ((fd = funix[i]) != -1 && FD_ISSET(fd, pReadfds)) {
readSocket(fd, i);
--nfds; /* indicate we have processed one */
}
}
}
+ freeFdSet(pReadfds);
RETiRet;
ENDrunInput
@@ -300,13 +315,22 @@ 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;
/* initialize and return if will run or not */
for (i = startIndexUxLocalSockets ; i < nfunix ; i++) {
- if ((funix[i] = create_unix_socket((char*) funixn[i])) != -1)
+ if ((funix[i] = create_unix_socket((char*) funixn[i], funixCreateSockPath[i])) != -1)
dbgprintf("Opened UNIX socket '%s' (fd %d).\n", funixn[i], funix[i]);
}
@@ -329,7 +353,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 */
@@ -376,6 +400,7 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
nfunix = 1;
bIgnoreTimestamp = 1;
bUseFlowCtl = 0;
+ bCreateSockPath = DFLT_bCreateSockPath;
return RS_RET_OK;
}
@@ -409,6 +434,8 @@ CODEmodInit_QueryRegCFSLineHdlr
NULL, &pLogHostName, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensocketflowcontrol", 0, eCmdHdlrBinary,
NULL, &bUseFlowCtl, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensocketcreatepath", 0, eCmdHdlrBinary,
+ NULL, &bCreateSockPath, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"addunixlistensocket", 0, eCmdHdlrGetWord,
addLstnSocketName, NULL, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
diff --git a/plugins/omoracle/omoracle.c b/plugins/omoracle/omoracle.c
index 331b7dd4..48ee1fa4 100644
--- a/plugins/omoracle/omoracle.c
+++ b/plugins/omoracle/omoracle.c
@@ -47,9 +47,9 @@
$OmoracleStatement \
insert into foo(hostname,message)values(:host,:message)
- Also note that identifiers to placeholders are arbitrarry. You
- need to define the properties on the template in the correct order
- you want them passed to the statement!
+ Also note that identifiers to placeholders are arbitrary. You need
+ to define the properties on the template in the correct order you
+ want them passed to the statement!
This file is licensed under the terms of the GPL version 3 or, at
your choice, any later version. Exceptionally (perhaps), you are
@@ -87,7 +87,8 @@ MODULE_TYPE_OUTPUT
DEF_OMOD_STATIC_DATA
DEFobjCurrIf(errmsg)
-/** */
+/** Structure defining a batch of items to be sent to the database in
+ * the same statement execution. */
struct oracle_batch
{
/* Batch size */
@@ -162,8 +163,10 @@ static int oci_errors(void* handle, ub4 htype, sword status)
return OCI_SUCCESS;
break;
case OCI_SUCCESS_WITH_INFO:
- errmsg.LogError(0, NO_ERRCODE, "OCI SUCCESS - With info\n");
- break;
+ OCIErrorGet(handle, 1, NULL, &errcode, buf, sizeof buf, htype);
+ errmsg.LogError(0, NO_ERRCODE, "OCI SUCCESS - With info: %s",
+ buf);
+ return OCI_SUCCESS_WITH_INFO;
case OCI_NEED_DATA:
errmsg.LogError(0, NO_ERRCODE, "OCI NEEDS MORE DATA\n");
break;
@@ -180,6 +183,9 @@ static int oci_errors(void* handle, ub4 htype, sword status)
break;
case OCI_INVALID_HANDLE:
errmsg.LogError(0, NO_ERRCODE, "OCI INVALID HANDLE\n");
+ /* In this case we may have to trigger a call to
+ * tryResume(). */
+ return RS_RET_SUSPENDED;
break;
case OCI_STILL_EXECUTING:
errmsg.LogError(0, NO_ERRCODE, "Still executing...\n");
@@ -332,6 +338,48 @@ CODESTARTcreateInstance
finalize_it:
ENDcreateInstance
+/* Analyses the errors during a batch statement execution, and logs
+ * all the corresponding ORA-MESSAGES, together with some useful
+ * information. */
+static void log_detailed_err(instanceData* pData)
+{
+ DEFiRet;
+ int errs, i, row, code, j;
+ OCIError *er = NULL, *er2 = NULL;
+ unsigned char buf[MAX_BUFSIZE];
+
+ OCIAttrGet(pData->statement, OCI_HTYPE_STMT, &errs, 0,
+ OCI_ATTR_NUM_DML_ERRORS, pData->error);
+ errmsg.LogError(0, NO_ERRCODE, "OCI: %d errors in execution of "
+ "statement: %s", errs, pData->txt_statement);
+
+ CHECKENV(pData->environment,
+ OCIHandleAlloc(pData->environment, &er, OCI_HTYPE_ERROR,
+ 0, NULL));
+ CHECKENV(pData->environment,
+ OCIHandleAlloc(pData->environment, &er2, OCI_HTYPE_ERROR,
+ 0, NULL));
+
+ for (i = 0; i < errs; i++) {
+ OCIParamGet(pData->error, OCI_HTYPE_ERROR,
+ er2, &er, i);
+ OCIAttrGet(er, OCI_HTYPE_ERROR, &row, 0,
+ OCI_ATTR_DML_ROW_OFFSET, er2);
+ errmsg.LogError(0, NO_ERRCODE, "OCI failure in row %d:", row);
+ for (j = 0; j < pData->batch.arguments; j++)
+ errmsg.LogError(0, NO_ERRCODE, "%s",
+ pData->batch.parameters[j][row]);
+ OCIErrorGet(er, 1, NULL, &code, buf, sizeof buf,
+ OCI_HTYPE_ERROR);
+ errmsg.LogError(0, NO_ERRCODE, "FAILURE DETAILS: %s", buf);
+ }
+
+finalize_it:
+ OCIHandleFree(er, OCI_HTYPE_ERROR);
+ OCIHandleFree(er2, OCI_HTYPE_ERROR);
+}
+
+
/* Inserts all stored statements into the database, releasing any
* allocated memory. */
static int insert_to_db(instanceData* pData)
@@ -346,6 +394,10 @@ static int insert_to_db(instanceData* pData)
OCI_BATCH_ERRORS));
finalize_it:
+ if (iRet == OCI_SUCCESS_WITH_INFO) {
+ log_detailed_err(pData);
+ iRet = RS_RET_OK;
+ }
pData->batch.n = 0;
OCITransCommit(pData->service, pData->error, 0);
dbgprintf ("omoracle insertion to DB %s\n", iRet == RS_RET_OK ?
diff --git a/runtime/Makefile.am b/runtime/Makefile.am
index 14abe722..ac006bca 100644
--- a/runtime/Makefile.am
+++ b/runtime/Makefile.am
@@ -9,12 +9,14 @@ librsyslog_la_SOURCES = \
rsyslog.h \
unicode-helper.h \
atomic.h \
+ atomic-posix-sem.c \
syslogd-types.h \
module-template.h \
obj-types.h \
nsd.h \
glbl.h \
glbl.c \
+ unlimited_select.h \
conf.c \
conf.h \
parser.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 d5aaf56b..ea3be37a 100644
--- a/runtime/atomic.h
+++ b/runtime/atomic.h
@@ -53,6 +53,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
@@ -66,6 +182,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/debug.c b/runtime/debug.c
index 9b7c2952..c82a411d 100644
--- a/runtime/debug.c
+++ b/runtime/debug.c
@@ -1280,11 +1280,11 @@ dbgGetRuntimeOptions(void)
/* this is earlier in the process than the -d option, as such it
* allows us to spit out debug messages from the very beginning.
*/
- Debug = 1;
+ Debug = DEBUG_FULL;
debugging_on = 1;
} else if(!strcasecmp((char*)optname, "debugondemand")) {
/* Enables debugging, but turns off debug output */
- Debug = 1;
+ Debug = DEBUG_ONDEMAND;
debugging_on = 1;
dbgprintf("Note: debug on demand turned on via configuraton file, "
"use USR1 signal to activate.\n");
diff --git a/runtime/debug.h b/runtime/debug.h
index dcbfb930..cfdf819c 100644
--- a/runtime/debug.h
+++ b/runtime/debug.h
@@ -29,6 +29,11 @@
#include <pthread.h>
#include "obj-types.h"
+/* some settings for various debug modes */
+#define DEBUG_OFF 0
+#define DEBUG_ONDEMAND 1
+#define DEBUG_FULL 2
+
/* external static data elements (some time to be replaced) */
extern int Debug; /* debug flag - read-only after startup */
extern int debugging_on; /* read-only, except on sig USR1 */
diff --git a/runtime/glbl.c b/runtime/glbl.c
index 7fa61963..58558ed2 100644
--- a/runtime/glbl.c
+++ b/runtime/glbl.c
@@ -72,6 +72,9 @@ static uchar *pszDfltNetstrmDrvr = NULL; /* module name of default netstream dri
static uchar *pszDfltNetstrmDrvrCAF = NULL; /* default CA file for the netstrm driver */
static uchar *pszDfltNetstrmDrvrKeyFile = NULL; /* default key file for the netstrm driver (server) */
static uchar *pszDfltNetstrmDrvrCertFile = NULL; /* default cert file for the netstrm driver (server) */
+#ifdef USE_UNLIMITED_SELECT
+static int iFdSetSize = howmany(FD_SETSIZE, __NFDBITS) * sizeof (fd_mask); /* size of select() bitmask in bytes */
+#endif
/* define a macro for the simple properties' set and get functions
@@ -104,6 +107,9 @@ SIMP_PROP(DisableDNS, bDisableDNS, int)
SIMP_PROP(LocalDomain, LocalDomain, uchar*)
SIMP_PROP(StripDomains, StripDomains, char**)
SIMP_PROP(LocalHosts, LocalHosts, char**)
+#ifdef USE_UNLIMITED_SELECT
+SIMP_PROP(FdSetSize, iFdSetSize, int)
+#endif
SIMP_PROP_SET(LocalFQDNName, LocalFQDNName, uchar*)
SIMP_PROP_SET(LocalHostName, LocalHostName, uchar*)
@@ -261,6 +267,9 @@ CODESTARTobjQueryInterface(glbl)
SIMP_PROP(DfltNetstrmDrvrCAF)
SIMP_PROP(DfltNetstrmDrvrKeyFile)
SIMP_PROP(DfltNetstrmDrvrCertFile)
+#ifdef USE_UNLIMITED_SELECT
+ SIMP_PROP(FdSetSize)
+#endif
#undef SIMP_PROP
finalize_it:
ENDobjQueryInterface(glbl)
@@ -295,6 +304,9 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
bOptimizeUniProc = 1;
bHUPisRestart = 0;
bPreserveFQDN = 0;
+#ifdef USE_UNLIMITED_SELECT
+ iFdSetSize = howmany(FD_SETSIZE, __NFDBITS) * sizeof (fd_mask);
+#endif
return RS_RET_OK;
}
diff --git a/runtime/glbl.h b/runtime/glbl.h
index dcfb6d5f..6a332576 100644
--- a/runtime/glbl.h
+++ b/runtime/glbl.h
@@ -62,9 +62,18 @@ BEGINinterface(glbl) /* name must also be changed in ENDinterface macro! */
/* added v3, 2009-06-30 */
rsRetVal (*GenerateLocalHostNameProperty)(void);
prop_t* (*GetLocalHostNameProp)(void);
+ /* note: v4, v5 are already used by more recent versions, so we need to skip them! */
+ /* added v6, 2009-11-16 as part of varmojfekoj's "unlimited select()" patch
+ * Note that it must be always present, otherwise the interface would have different
+ * versions depending on compile settings, what is not acceptable.
+ * Use this property with care, it is only truly available if UNLIMITED_SELECT is enabled
+ * (I did not yet further investigate the details, because that code hopefully can be removed
+ * at some later stage).
+ */
+ SIMP_PROP(FdSetSize, int)
#undef SIMP_PROP
ENDinterface(glbl)
-#define glblCURR_IF_VERSION 3 /* increment whenever you change the interface structure! */
+#define glblCURR_IF_VERSION 6 /* increment whenever you change the interface structure! */
/* version 2 had PreserveFQDN added - rgerhards, 2008-12-08 */
/* the remaining prototypes */
diff --git a/runtime/nsdsel_ptcp.c b/runtime/nsdsel_ptcp.c
index 41b85e0c..e2cfca7c 100644
--- a/runtime/nsdsel_ptcp.c
+++ b/runtime/nsdsel_ptcp.c
@@ -36,6 +36,7 @@
#include "errmsg.h"
#include "nsd_ptcp.h"
#include "nsdsel_ptcp.h"
+#include "unlimited_select.h"
/* static data */
DEFobjStaticHelpers
@@ -47,14 +48,23 @@ DEFobjCurrIf(glbl)
*/
BEGINobjConstruct(nsdsel_ptcp) /* be sure to specify the object type also in END macro! */
pThis->maxfds = 0;
+#ifdef USE_UNLIMITED_SELECT
+ pThis->pReadfds = calloc(1, glbl.GetFdSetSize());
+ pThis->pWritefds = calloc(1, glbl.GetFdSetSize());
+#else
FD_ZERO(&pThis->readfds);
FD_ZERO(&pThis->writefds);
+#endif
ENDobjConstruct(nsdsel_ptcp)
/* destructor for the nsdsel_ptcp object */
BEGINobjDestruct(nsdsel_ptcp) /* be sure to specify the object type also in END and CODESTART macros! */
CODESTARTobjDestruct(nsdsel_ptcp)
+#ifdef USE_UNLIMITED_SELECT
+ freeFdSet(pThis->pReadfds);
+ freeFdSet(pThis->pWritefds);
+#endif
ENDobjDestruct(nsdsel_ptcp)
@@ -65,20 +75,27 @@ Add(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp)
DEFiRet;
nsdsel_ptcp_t *pThis = (nsdsel_ptcp_t*) pNsdsel;
nsd_ptcp_t *pSock = (nsd_ptcp_t*) pNsd;
+#ifdef USE_UNLIMITED_SELECT
+ fd_set *pReadfds = pThis->pReadfds;
+ fd_set *pWritefds = pThis->pWritefds;
+#else
+ fd_set *pReadfds = &pThis->readfds;
+ fd_set *pWritefds = &pThis->writefds;
+#endif
ISOBJ_TYPE_assert(pSock, nsd_ptcp);
ISOBJ_TYPE_assert(pThis, nsdsel_ptcp);
switch(waitOp) {
case NSDSEL_RD:
- FD_SET(pSock->sock, &pThis->readfds);
+ FD_SET(pSock->sock, pReadfds);
break;
case NSDSEL_WR:
- FD_SET(pSock->sock, &pThis->writefds);
+ FD_SET(pSock->sock, pWritefds);
break;
case NSDSEL_RDWR:
- FD_SET(pSock->sock, &pThis->readfds);
- FD_SET(pSock->sock, &pThis->writefds);
+ FD_SET(pSock->sock, pReadfds);
+ FD_SET(pSock->sock, pWritefds);
break;
}
@@ -98,6 +115,13 @@ Select(nsdsel_t *pNsdsel, int *piNumReady)
DEFiRet;
int i;
nsdsel_ptcp_t *pThis = (nsdsel_ptcp_t*) pNsdsel;
+#ifdef USE_UNLIMITED_SELECT
+ fd_set *pReadfds = pThis->pReadfds;
+ fd_set *pWritefds = pThis->pWritefds;
+#else
+ fd_set *pReadfds = &pThis->readfds;
+ fd_set *pWritefds = &pThis->writefds;
+#endif
ISOBJ_TYPE_assert(pThis, nsdsel_ptcp);
assert(piNumReady != NULL);
@@ -106,13 +130,13 @@ Select(nsdsel_t *pNsdsel, int *piNumReady)
// TODO: name in dbgprintf!
dbgprintf("--------<NSDSEL_PTCP> calling select, active fds (max %d): ", pThis->maxfds);
for(i = 0; i <= pThis->maxfds; ++i)
- if(FD_ISSET(i, &pThis->readfds) || FD_ISSET(i, &pThis->writefds))
+ if(FD_ISSET(i, pReadfds) || FD_ISSET(i, pWritefds))
dbgprintf("%d ", i);
dbgprintf("\n");
}
/* now do the select */
- *piNumReady = select(pThis->maxfds+1, &pThis->readfds, &pThis->writefds, NULL, NULL);
+ *piNumReady = select(pThis->maxfds+1, pReadfds, pWritefds, NULL, NULL);
RETiRet;
}
@@ -125,6 +149,13 @@ IsReady(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp, int *pbIsReady)
DEFiRet;
nsdsel_ptcp_t *pThis = (nsdsel_ptcp_t*) pNsdsel;
nsd_ptcp_t *pSock = (nsd_ptcp_t*) pNsd;
+#ifdef USE_UNLIMITED_SELECT
+ fd_set *pReadfds = pThis->pReadfds;
+ fd_set *pWritefds = pThis->pWritefds;
+#else
+ fd_set *pReadfds = &pThis->readfds;
+ fd_set *pWritefds = &pThis->writefds;
+#endif
ISOBJ_TYPE_assert(pThis, nsdsel_ptcp);
ISOBJ_TYPE_assert(pSock, nsd_ptcp);
@@ -132,14 +163,14 @@ IsReady(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp, int *pbIsReady)
switch(waitOp) {
case NSDSEL_RD:
- *pbIsReady = FD_ISSET(pSock->sock, &pThis->readfds);
+ *pbIsReady = FD_ISSET(pSock->sock, pReadfds);
break;
case NSDSEL_WR:
- *pbIsReady = FD_ISSET(pSock->sock, &pThis->writefds);
+ *pbIsReady = FD_ISSET(pSock->sock, pWritefds);
break;
case NSDSEL_RDWR:
- *pbIsReady = FD_ISSET(pSock->sock, &pThis->readfds)
- | FD_ISSET(pSock->sock, &pThis->writefds);
+ *pbIsReady = FD_ISSET(pSock->sock, pReadfds)
+ | FD_ISSET(pSock->sock, pWritefds);
break;
}
diff --git a/runtime/nsdsel_ptcp.h b/runtime/nsdsel_ptcp.h
index 6c0c7fa7..f9ec8210 100644
--- a/runtime/nsdsel_ptcp.h
+++ b/runtime/nsdsel_ptcp.h
@@ -31,8 +31,13 @@ typedef nsdsel_if_t nsdsel_ptcp_if_t; /* we just *implement* this interface */
struct nsdsel_ptcp_s {
BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
int maxfds;
+#ifdef USE_UNLIMITED_SELECT
+ fd_set *pReadfds;
+ fd_set *pWritefds;
+#else
fd_set readfds;
fd_set writefds;
+#endif
};
/* interface is defined in nsd.h, we just implement it! */
diff --git a/runtime/rsyslog.c b/runtime/rsyslog.c
index 443d0f41..5750ca76 100644
--- a/runtime/rsyslog.c
+++ b/runtime/rsyslog.c
@@ -80,6 +80,7 @@
#include "prop.h"
#include "rule.h"
#include "ruleset.h"
+#include "atomic.h"
/* forward definitions */
static rsRetVal dfltErrLogger(int, uchar *errMsg);
@@ -139,6 +140,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
@@ -215,6 +222,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/runtime/unlimited_select.h b/runtime/unlimited_select.h
new file mode 100644
index 00000000..32dadc03
--- /dev/null
+++ b/runtime/unlimited_select.h
@@ -0,0 +1,45 @@
+/* unlimited_select.h
+ * Tweak the macros for accessing fd_set so that the select() syscall
+ * won't be limited to a particular number of file descriptors.
+ *
+ * Copyright 2009 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.
+ */
+
+#ifndef UNLIMITED_SELECT_H_INCLUDED
+
+#include <string.h>
+#include <stdlib.h>
+#include <sys/select.h>
+#include "glbl.h"
+
+#ifdef USE_UNLIMITED_SELECT
+# undef FD_ZERO
+# define FD_ZERO(set) memset((set), 0, glbl.GetFdSetSize());
+#endif
+
+#ifdef USE_UNLIMITED_SELECT
+void freeFdSet(fd_set *p) {
+ free(p);
+}
+#else
+# define freeFdSet(x)
+#endif
+
+#endif /* #ifndef UNLIMITED_SELECT_H_INCLUDED */
diff --git a/runtime/vm.c b/runtime/vm.c
index aaf3c879..0ed174d1 100644
--- a/runtime/vm.c
+++ b/runtime/vm.c
@@ -34,6 +34,7 @@
#include "vm.h"
#include "sysvar.h"
#include "stringbuf.h"
+#include "unicode-helper.h"
/* static data */
DEFobjStaticHelpers
@@ -41,6 +42,8 @@ DEFobjCurrIf(vmstk)
DEFobjCurrIf(var)
DEFobjCurrIf(sysvar)
+static pthread_mutex_t mutGetenv; /* we need to make this global because otherwise we can not guarantee proper init! */
+
/* ------------------------------ function registry code and structures ------------------------------ */
/* we maintain a registry of known functions */
@@ -542,6 +545,42 @@ finalize_it:
}
+/* The getenv function. Note that we guard the OS call by a mutex, as that
+ * function is not guaranteed to be thread-safe. This implementation here is far from
+ * being optimal, at least we should cache the result. This is left TODO for
+ * a later revision.
+ * rgerhards, 2009-11-03
+ */
+static rsRetVal
+rsf_getenv(vmstk_t *pStk, int numOperands)
+{
+ DEFiRet;
+ var_t *operand1;
+ char *envResult;
+ cstr_t *pCstr;
+
+ if(numOperands != 1)
+ ABORT_FINALIZE(RS_RET_INVLD_NBR_ARGUMENTS);
+
+ /* pop args and do operaton (trivial case here...) */
+ vmstk.PopString(pStk, &operand1);
+ d_pthread_mutex_lock(&mutGetenv);
+ envResult = getenv((char*) rsCStrGetSzStr(operand1->val.pStr));
+ DBGPRINTF("rsf_getenv(): envvar '%s', return '%s'\n", rsCStrGetSzStr(operand1->val.pStr),
+ envResult == NULL ? "(NULL)" : envResult);
+ iRet = rsCStrConstructFromszStr(&pCstr, (envResult == NULL) ? UCHAR_CONSTANT("") : (uchar*)envResult);
+ d_pthread_mutex_unlock(&mutGetenv);
+ if(iRet != RS_RET_OK)
+ FINALIZE; /* need to do this after mutex is unlocked! */
+
+ /* Store result and cleanup */
+ var.SetString(operand1, pCstr);
+ vmstk.Push(pStk, operand1);
+finalize_it:
+ RETiRet;
+}
+
+
/* The "tolower" function, which converts its sole argument to lower case.
* Quite honestly, currently this is primarily a test driver for me...
* rgerhards, 2009-04-06
@@ -759,6 +798,8 @@ BEGINObjClassExit(vm, OBJ_IS_CORE_MODULE) /* class, version */
objRelease(sysvar, CORE_COMPONENT);
objRelease(var, CORE_COMPONENT);
objRelease(vmstk, CORE_COMPONENT);
+
+ pthread_mutex_destroy(&mutGetenv);
ENDObjClassExit(vm)
@@ -779,6 +820,9 @@ BEGINObjClassInit(vm, 1, OBJ_IS_CORE_MODULE) /* class, version */
/* register built-in functions // TODO: move to its own module */
CHKiRet(rsfrAddFunction((uchar*)"strlen", rsf_strlen));
CHKiRet(rsfrAddFunction((uchar*)"tolower", rsf_tolower));
+ CHKiRet(rsfrAddFunction((uchar*)"getenv", rsf_getenv));
+
+ pthread_mutex_init(&mutGetenv, NULL);
ENDObjClassInit(vm)
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 0045f00a..a43f305e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,12 +1,13 @@
if ENABLE_TESTBENCH
TESTRUNS = rt_init rscript
-check_PROGRAMS = $(TESTRUNS) ourtail nettester tcpflood chkseq randomgen
+check_PROGRAMS = $(TESTRUNS) ourtail nettester tcpflood chkseq msleep randomgen
TESTS = $(TESTRUNS) cfg.sh \
validation-run.sh \
imtcp-multiport.sh \
diskqueue.sh \
diskqueue-fsync.sh \
manytcp.sh \
+ rsf_getenv.sh \
sndrcv.sh \
sndrcv_gzip.sh \
asynwr_simple.sh \
@@ -128,6 +129,8 @@ EXTRA_DIST= 1.rstest 2.rstest 3.rstest err1.rstest \
killrsyslog.sh \
parsertest.sh \
fieldtest.sh \
+ rsf_getenv.sh \
+ testsuites/rsf_getenv.conf \
diskqueue.sh \
testsuites/diskqueue.conf \
diskqueue-fsync.sh \
@@ -205,6 +208,7 @@ 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
diff --git a/tests/complex1.sh b/tests/complex1.sh
index 7f3cd994..b3e31b30 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 51ad5f6a..54232a37 100755
--- a/tests/diag.sh
+++ b/tests/diag.sh
@@ -10,7 +10,7 @@
#valgrind="valgrind --tool=helgrind --log-fd=1"
#valgrind="valgrind --tool=exp-ptrcheck --log-fd=1"
#set -o xtrace
-#export RSYSLOG_DEBUG="debug nostdout printmutexaction"
+#export RSYSLOG_DEBUG="debug nostdout noprintmutexaction"
#export RSYSLOG_DEBUGLOG="log"
case $1 in
'init') $srcdir/killrsyslog.sh # kill rsyslogd if it runs for some reason
@@ -38,16 +38,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
;;
'wait-queueempty') # wait for main message queue to be empty. $2 is the instance.
@@ -131,5 +129,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 e1ecbcb5..24e20422 100644
--- a/tests/nettester.c
+++ b/tests/nettester.c
@@ -62,7 +62,7 @@ static char *testSuite = NULL; /* name of current test suite */
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 useDebugEnv = 0; /* activate debugging environment (for rsyslog debug log)? */
+static char **ourEnvp;
/* these two are quick hacks... */
int iFailed = 0;
@@ -117,6 +117,10 @@ void readLine(int fd, char *ln)
* We use traditional framing '\n' at EOR for this tester. It may be
* worth considering additional framing modes.
* rgerhards, 2009-04-08
+ * Note: we re-create the socket within the retry loop, because this
+ * seems to be needed under Solaris. If we do not do that, we run
+ * into troubles (maybe something wrongly initialized then?)
+ * -- rgerhards, 2010-04-12
*/
int
tcpSend(char *buf, int lenBuf)
@@ -124,30 +128,34 @@ tcpSend(char *buf, int lenBuf)
static int sock = INVALID_SOCKET;
struct sockaddr_in addr;
int retries;
+ int ret;
+ int iRet = 0; /* 0 OK, anything else error */
if(sock == INVALID_SOCKET) {
/* first time, need to connect to target */
- if((sock=socket(AF_INET, SOCK_STREAM, 0))==-1) {
- perror("socket()");
- return(1);
- }
-
- memset((char *) &addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(iPort);
- if(inet_aton("127.0.0.1", &addr.sin_addr)==0) {
- fprintf(stderr, "inet_aton() failed\n");
- return(1);
- }
retries = 0;
while(1) { /* loop broken inside */
- if(connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == 0) {
+ /* first time, need to connect to target */
+ if((sock=socket(AF_INET, SOCK_STREAM, 0))==-1) {
+ perror("socket()");
+ iRet = 1;
+ goto finalize_it;
+ }
+ memset((char *) &addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(iPort);
+ if(inet_aton("127.0.0.1", &addr.sin_addr)==0) {
+ fprintf(stderr, "inet_aton() failed\n");
+ iRet = 1;
+ goto finalize_it;
+ }
+ if((ret = connect(sock, (struct sockaddr*)&addr, sizeof(addr))) == 0) {
break;
} else {
if(retries++ == 50) {
- ++iFailed;
fprintf(stderr, "connect() failed\n");
- return(1);
+ iRet = 1;
+ goto finalize_it;
} else {
usleep(100000); /* 0.1 sec, these are us! */
}
@@ -156,20 +164,32 @@ tcpSend(char *buf, int lenBuf)
}
/* send test data */
- if(send(sock, buf, lenBuf, 0) != lenBuf) {
+ if((ret = send(sock, buf, lenBuf, 0)) != lenBuf) {
perror("send test data");
- fprintf(stderr, "send() failed\n");
- return(1);
+ fprintf(stderr, "send() failed, sock=%d, ret=%d\n", sock, ret);
+ iRet = 1;
+ goto finalize_it;
}
/* send record terminator */
if(send(sock, "\n", 1, 0) != 1) {
perror("send record terminator");
fprintf(stderr, "send() failed\n");
- return(1);
+ iRet = 1;
+ goto finalize_it;
}
- return 0;
+finalize_it:
+ if(iRet != 0) {
+ /* need to do some (common) cleanup */
+ if(sock != INVALID_SOCKET) {
+ close(sock);
+ sock = INVALID_SOCKET;
+ }
+ ++iFailed;
+ }
+
+ return iRet;
}
@@ -218,9 +238,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 };
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);
@@ -243,8 +260,9 @@ 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 {
+ usleep(10000);
close(pipefd[1]);
*pid = cpid;
*pfd = pipefd[0];
@@ -364,6 +382,7 @@ processTestFile(int fd, char *pszFileName)
expected[strlen(expected)-1] = '\0'; /* remove \n */
/* pull response from server and then check if it meets our expectation */
+//printf("try pull pipe...\n");
readLine(fd, buf);
if(strcmp(expected, buf)) {
++iFailed;
@@ -426,7 +445,8 @@ doTests(int fd, char *files)
printf("Error: no test cases found, no tests executed.\n");
iFailed = 1;
} else {
- printf("Number of tests run: %d, number of failures: %d\n", iTests, iFailed);
+ printf("Number of tests run: %3d, number of failures: %d, test: %s/%s\n",
+ iTests, iFailed, testSuite, inputMode2Str(inputMode));
}
return(iFailed);
@@ -450,7 +470,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;
@@ -459,14 +479,12 @@ int main(int argc, char *argv[])
char buf[4096];
char testcases[4096];
+ ourEnvp = envp;
while((opt = getopt(argc, argv, "dc:i:p:t:v")) != EOF) {
switch((char)opt) {
case 'c':
pszCustomConf = optarg;
break;
- case 'd':
- useDebugEnv = 1;
- break;
case 'i':
if(!strcmp(optarg, "udp"))
inputMode = inputUDP;
@@ -520,6 +538,11 @@ int main(int argc, char *argv[])
}
fclose(fp);
+ /* make sure we do not abort if there is an issue with pipes.
+ * our code does the necessary error handling.
+ */
+ sigset(SIGPIPE, SIG_IGN);
+
/* start to be tested rsyslogd */
openPipe(testSuite, &rsyslogdPid, &fd);
readLine(fd, buf);
diff --git a/tests/rsf_getenv.sh b/tests/rsf_getenv.sh
new file mode 100755
index 00000000..fd083bce
--- /dev/null
+++ b/tests/rsf_getenv.sh
@@ -0,0 +1,17 @@
+# Test for the getenv() rainerscript function
+# this is a quick test, but it gurantees that the code path is
+# at least progressed (but we do not check for unset envvars!)
+# added 2009-11-03 by Rgerhards
+# This file is part of the rsyslog project, released under GPLv3
+# uncomment for debugging support:
+echo ===============================================================================
+echo \[rsf_getenv.sh\]: testing RainerScript getenv\(\) function
+export MSGNUM="msgnum:"
+source $srcdir/diag.sh init
+source $srcdir/diag.sh startup rsf_getenv.conf
+source $srcdir/diag.sh tcpflood -m10000
+source $srcdir/diag.sh shutdown-when-empty # shut down rsyslogd when done processing messages
+source $srcdir/diag.sh wait-shutdown
+source $srcdir/diag.sh seq-check 0 9999
+unset MSGNUM
+source $srcdir/diag.sh exit
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 d8c3f038..e92d1308 100644
--- a/tests/tcpflood.c
+++ b/tests/tcpflood.c
@@ -62,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
@@ -439,6 +440,20 @@ int main(int argc, char *argv[])
}
}
+ 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);
diff --git a/tests/testsuites/rsf_getenv.conf b/tests/testsuites/rsf_getenv.conf
new file mode 100644
index 00000000..2f2eb58c
--- /dev/null
+++ b/tests/testsuites/rsf_getenv.conf
@@ -0,0 +1,17 @@
+# Test for RainerScript getenv() function (see .sh file for details)
+# Note envvar MSGNUM must be set to "msgnum:"
+# rgerhards, 2009-11-03
+$IncludeConfig diag-common.conf
+
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$MainMsgQueueTimeoutShutdown 10000
+$InputTCPServerRun 13514
+
+# set spool locations and switch queue to disk-only mode
+$WorkDirectory test-spool
+$MainMsgQueueFilename mainq
+$MainMsgQueueType disk
+
+$template outfmt,"%msg:F,58:2%\n"
+$template dynfile,"rsyslog.out.log" # trick to use relative path names!
+if $msg contains getenv('MSGNUM') then ?dynfile;outfmt
diff --git a/tools/omfile.c b/tools/omfile.c
index 24de052c..74b22019 100644
--- a/tools/omfile.c
+++ b/tools/omfile.c
@@ -89,11 +89,13 @@ typedef struct s_dynaFileCacheEntry dynaFileCacheEntry;
#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 */
static int iDynaFileCacheSize = 10; /* max cache for dynamic files */
static int fCreateMode = 0644; /* mode to use when creating files */
static int fDirCreateMode = 0700; /* mode to use when creating files */
static int bFailOnChown; /* fail if chown fails? */
+static int bForceChown = DFLT_bForceChown; /* Force chown() on existing files? */
static uid_t fileUID; /* UID to be used for newly created files */
static uid_t fileGID; /* GID to be used for newly created files */
static uid_t dirUID; /* UID to be used for newly created directories */
@@ -118,6 +120,7 @@ typedef struct _instanceData {
int fDirCreateMode; /* creation mode for mkdir() */
int bCreateDirs; /* auto-create directories? */
int bSyncFile; /* should the file by sync()'ed? 1- yes, 0- no */
+ bool bForceChown; /* force chown() on existing files? */
uid_t fileUID; /* IDs for creation */
uid_t dirUID;
gid_t fileGID;
@@ -164,6 +167,7 @@ CODESTARTdbgPrintInstInfo
dbgprintf("\tfile cache size=%d\n", pData->iDynaFileCacheSize);
dbgprintf("\tcreate directories: %s\n", pData->bCreateDirs ? "yes" : "no");
dbgprintf("\tfile owner %d, group %d\n", pData->fileUID, pData->fileGID);
+ dbgprintf("\tforce chown() for all files: %s\n", pData->bForceChown ? "yes" : "no");
dbgprintf("\tdirectory owner %d, group %d\n", pData->dirUID, pData->dirGID);
dbgprintf("\tdir create mode 0%3.3o, file create mode 0%3.3o\n",
pData->fDirCreateMode, pData->fCreateMode);
@@ -351,7 +355,22 @@ prepareFile(instanceData *pData, uchar *newFileName)
int fd;
DEFiRet;
- if(access((char*)newFileName, F_OK) != 0) {
+ if(access((char*)newFileName, F_OK) == 0) {
+ if(pData->bForceChown) {
+ /* Try to fix wrong ownership set by someone else. Note that this code
+ * will no longer work once we have made the $PrivDrop code fully secure.
+ * This change is based on an idea of Michael Terry, provided as part of
+ * the effort to make rsyslogd the Ubuntu default syslogd.
+ * rgerhards, 2009-09-11
+ */
+ if(chown((char*)newFileName, pData->fileUID, pData->fileGID) != 0) {
+ if(pData->bFailOnChown) {
+ int eSave = errno;
+ errno = eSave;
+ }
+ }
+ }
+ } else {
/* file does not exist, create it (and eventually parent directories */
fd = -1;
if(pData->bCreateDirs) {
@@ -372,7 +391,7 @@ prepareFile(instanceData *pData, uchar *newFileName)
pData->fCreateMode);
if(fd != -1) {
/* check and set uid/gid */
- if(pData->fileUID != (uid_t)-1 || pData->fileGID != (gid_t) -1) {
+ if(pData->bForceChown || pData->fileUID != (uid_t)-1 || pData->fileGID != (gid_t) -1) {
/* we need to set owner/group */
if(fchown(fd, pData->fileUID, pData->fileGID) != 0) {
if(pData->bFailOnChown) {
@@ -724,6 +743,7 @@ CODESTARTparseSelectorAct
pData->fDirCreateMode = fDirCreateMode;
pData->bCreateDirs = bCreateDirs;
pData->bFailOnChown = bFailOnChown;
+ pData->bForceChown = bForceChown;
pData->fileUID = fileUID;
pData->fileGID = fileGID;
pData->dirUID = dirUID;
@@ -759,6 +779,7 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
dirUID = -1;
dirGID = -1;
bFailOnChown = 1;
+ bForceChown = DFLT_bForceChown;
iDynaFileCacheSize = 10;
fCreateMode = 0644;
fDirCreateMode = 0700;
@@ -826,6 +847,7 @@ CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(omsdRegCFSLineHdlr((uchar *)"filecreatemode", 0, eCmdHdlrFileCreateMode, NULL, &fCreateMode, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"createdirs", 0, eCmdHdlrBinary, NULL, &bCreateDirs, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"failonchownfailure", 0, eCmdHdlrBinary, NULL, &bFailOnChown, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileForceChown", 0, eCmdHdlrBinary, NULL, &bForceChown, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionfileenablesync", 0, eCmdHdlrBinary, NULL, &bEnableSync, STD_LOADABLE_MODULE_ID));
CHKiRet(regCfSysLineHdlr((uchar *)"actionfiledefaulttemplate", 0, eCmdHdlrGetWord, NULL, &pszFileDfltTplName, NULL));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
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 a03dcf0e..e318fd8e 100644
--- a/tools/syslogd.c
+++ b/tools/syslogd.c
@@ -254,11 +254,14 @@ int bDropTrailingLF = 1; /* drop trailing LF's on reception? */
int iCompatibilityMode = 0; /* version we should be compatible with; 0 means sysklogd. It is
the default, so if no -c<n> option is given, we make ourselvs
as compatible to sysklogd as possible. */
+#define DFLT_bLogStatusMsgs 1
+static int bLogStatusMsgs = DFLT_bLogStatusMsgs; /* log rsyslog start/stop/HUP messages? */
static int bDebugPrintTemplateList = 1;/* output template list in debug mode? */
static int bDebugPrintCfSysLineHandlerList = 1;/* output cfsyslinehandler list in debug mode? */
static int bDebugPrintModuleList = 1;/* output module list in debug mode? */
-uchar cCCEscapeChar = '\\';/* character to be used to start an escape sequence for control chars */
+uchar cCCEscapeChar = '#';/* character to be used to start an escape sequence for control chars */
int bEscapeCCOnRcv = 1; /* escape control characters on reception: 0 - no, 1 - yes */
+int bEscapeTab = 1; /* treat tab as escape control character: 0 - no, 1 - yes */
static int bErrMsgToStderr = 1; /* print error messages to stderr (in addition to everything else)? */
int bReduceRepeatMsgs; /* reduce repeated message - 0 - no, 1 - yes */
int bActExecWhenPrevSusp; /* execute action only when previous one was suspended? */
@@ -337,12 +340,14 @@ getFIOPName(unsigned iFIOP)
static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
{
cCCEscapeChar = '#';
+ bLogStatusMsgs = DFLT_bLogStatusMsgs;
bActExecWhenPrevSusp = 0;
iActExecOnceInterval = 0;
bDebugPrintTemplateList = 1;
bDebugPrintCfSysLineHandlerList = 1;
bDebugPrintModuleList = 1;
bEscapeCCOnRcv = 1; /* default is to escape control characters */
+ bEscapeTab = 1;
bReduceRepeatMsgs = 0;
free(pszMainMsgQFName);
pszMainMsgQFName = NULL;
@@ -809,7 +814,7 @@ parseAndSubmitMessage(uchar *hname, uchar *hnameIP, uchar *msg, int len, int fla
/* log an error? Very questionable... rgerhards, 2006-11-30 */
/* decided: we do not log an error, it won't help... rger, 2007-06-21 */
++pData;
- } else if(bEscapeCCOnRcv && iscntrl((int) *pData)) {
+ } else if(bEscapeCCOnRcv && iscntrl((int) *pData) && (*pData != '\t' || bEscapeTab)) {
/* we are configured to escape control characters. Please note
* that this most probably break non-western character sets like
* Japanese, Korean or Chinese. rgerhards, 2007-07-17
@@ -906,7 +911,7 @@ logmsgInternal(int iErr, int pri, uchar *msg, int flags)
* permits us to process unmodified config files which otherwise contain a
* supressor statement.
*/
- if(((Debug || NoFork) && bErrMsgToStderr) || iConfigVerify) {
+ if(((Debug == DEBUG_FULL || NoFork) && bErrMsgToStderr) || iConfigVerify) {
if(LOG_PRI(pri) == LOG_ERR)
fprintf(stderr, "rsyslogd: %s\n", msg);
}
@@ -1652,10 +1657,10 @@ static void doDie(int sig)
# define MSG1 "DoDie called.\n"
# define MSG2 "DoDie called 5 times - unconditional exit\n"
static int iRetries = 0; /* debug aid */
- if(Debug)
+ if(Debug == DEBUG_FULL)
write(1, MSG1, sizeof(MSG1) - 1);
if(iRetries++ == 4) {
- if(Debug)
+ if(Debug == DEBUG_FULL)
write(1, MSG2, sizeof(MSG2) - 1);
abort();
}
@@ -1721,7 +1726,7 @@ die(int sig)
thrdTerminateAll();
/* and THEN send the termination log message (see long comment above) */
- if (sig) {
+ if(sig && bLogStatusMsgs) {
(void) snprintf(buf, sizeof(buf) / sizeof(char),
" [origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
"\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"]" " exiting on signal %d.",
@@ -1842,6 +1847,9 @@ static rsRetVal setMaxFiles(void __attribute__((unused)) *pVal, int iFiles)
iFiles, errStr, (long) maxFiles.rlim_max);
ABORT_FINALIZE(RS_RET_ERR_RLIM_NOFILE);
}
+#ifdef USE_UNLIMITED_SELECT
+ glbl.SetFdSetSize(howmany(iFiles, __NFDBITS) * sizeof (fd_mask));
+#endif
DBGPRINTF("Max number of files set to %d [kernel max %ld].\n", iFiles, (long) maxFiles.rlim_max);
finalize_it:
@@ -2415,11 +2423,13 @@ init()
/* we now generate the startup message. It now includes everything to
* identify this instance. -- rgerhards, 2005-08-17
*/
- snprintf(bufStartUpMsg, sizeof(bufStartUpMsg)/sizeof(char),
- " [origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
- "\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"] (re)start",
- (int) myPid);
- logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar*)bufStartUpMsg, 0);
+ if(bLogStatusMsgs) {
+ snprintf(bufStartUpMsg, sizeof(bufStartUpMsg)/sizeof(char),
+ " [origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
+ "\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"] (re)start",
+ (int) myPid);
+ logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar*)bufStartUpMsg, 0);
+ }
memset(&sigAct, 0, sizeof (sigAct));
sigemptyset(&sigAct.sa_mask);
@@ -2568,12 +2578,14 @@ doHUP(void)
{
char buf[512];
- snprintf(buf, sizeof(buf) / sizeof(char),
- " [origin software=\"rsyslogd\" " "swVersion=\"" VERSION
- "\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"] rsyslogd was HUPed, type '%s'.",
- (int) myPid, glbl.GetHUPisRestart() ? "restart" : "lightweight");
- errno = 0;
- logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar*)buf, 0);
+ if(bLogStatusMsgs) {
+ snprintf(buf, sizeof(buf) / sizeof(char),
+ " [origin software=\"rsyslogd\" " "swVersion=\"" VERSION
+ "\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"] rsyslogd was HUPed, type '%s'.",
+ (int) myPid, glbl.GetHUPisRestart() ? "restart" : "lightweight");
+ errno = 0;
+ logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar*)buf, 0);
+ }
if(glbl.GetHUPisRestart()) {
DBGPRINTF("Received SIGHUP, configured to be restart, reloading rsyslogd.\n");
@@ -2697,6 +2709,7 @@ static rsRetVal loadBuildInModules(void)
* is that rsyslog will terminate if we can not register our built-in config commands.
* This, I think, is the right thing to do. -- rgerhards, 2007-07-31
*/
+ CHKiRet(regCfSysLineHdlr((uchar *)"logrsyslogstatusmessages", 0, eCmdHdlrBinary, NULL, &bLogStatusMsgs, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeretrycount", 0, eCmdHdlrInt, NULL, &glbliActionResumeRetryCount, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"defaultruleset", 0, eCmdHdlrGetWord, setDefaultRuleset, NULL, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"ruleset", 0, eCmdHdlrGetWord, setCurrRuleset, NULL, NULL));
@@ -2727,6 +2740,7 @@ static rsRetVal loadBuildInModules(void)
CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeinterval", 0, eCmdHdlrInt, setActionResumeInterval, NULL, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"controlcharacterescapeprefix", 0, eCmdHdlrGetChar, NULL, &cCCEscapeChar, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactersonreceive", 0, eCmdHdlrBinary, NULL, &bEscapeCCOnRcv, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactertab", 0, eCmdHdlrBinary, NULL, &bEscapeTab, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"droptrailinglfonreception", 0, eCmdHdlrBinary, NULL, &bDropTrailingLF, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"template", 0, eCmdHdlrCustomHandler, conf.doNameLine, (void*)DIR_TEMPLATE, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"outchannel", 0, eCmdHdlrCustomHandler, conf.doNameLine, (void*)DIR_OUTCHANNEL, NULL));
@@ -2884,7 +2898,7 @@ static rsRetVal mainThread()
* is still in its infancy (and not really done), we currently accept this issue.
* rgerhards, 2009-06-29
*/
- if(!(Debug || NoFork)) {
+ if(!(Debug == DEBUG_FULL || NoFork)) {
close(1);
close(2);
bErrMsgToStderr = 0;
@@ -3075,7 +3089,7 @@ doGlblProcessInit(void)
thrdInit();
- if( !(Debug || NoFork) )
+ if( !(Debug == DEBUG_FULL || NoFork) )
{
DBGPRINTF("Checking pidfile.\n");
if (!check_pid(PidFile))
@@ -3174,6 +3188,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
@@ -3260,8 +3275,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. */